在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
1. go协程调用跟切换比线程效率高。 线程是内核对外提供的服务,应用程序可以通过系统调用让内核启动线程,由内核来负责线程调度和切换。线程在等待IO操作时线程变为unrunnable状态会触发上下文切换。现代操作系统一般都采用抢占式调度,上下文切换一般发生在时钟中断和系统调用返回前,调度器计算当前线程的时间片,如果需要切换就从运行队列中选出一个目标线程,保存当前线程的环境,并且恢复目标线程的运行环境,最典型的就是切换ESP指向目标线程内核堆栈,将EIP指向目标线程上次被调度出时的指令地址。 go协程是不依赖操作系统和其提供的线程,golang自己实现的CSP并发模型实现(MPG),同时go协程也叫用户态线程,协程之间的切换发生在用户态,很轻量。在用户态没有时钟中断,系统调用等机制, 因此效率比较高。
2. go协程占用内存少。 执行go协程只需要极少的栈内存(大概是4~5KB),默认情况下,而线程栈的大小为1MB。goroutine就是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。所以它非常廉价,我们可以很轻松的创建上万个goroutine,但它们并不是被操作系统所调度执行。
2. 数组与切片比较 数组: 1. 数组是具有固定长度的,并且拥有0个或者多个相同元素的数据类型,数组在使用前必须确定数组长度,。 2. 数组的长度是数组类型的一部分,比如[3]int 和 [4]int是两种不同类型的数组,可以通过内置函数len(array)来获取数组的长度。 3. 数组需要指定大小,如果不指定会根据初始化来自动推算出大小,在初始化之后不可改变,无法修改其长度。 4. 数组是值传递。 5. 数组是内置(build-in)类型,是一组同一类型数据的集合,它是值类型。 6. 和php等语言一样,go数组从0开始的下标索引来访问数组元素。
切片: 1. 切片表示一个拥有相同类型的可变长度的序列。它对底层的数组(内部是通过数组保存数据的)进行了抽象,并提供相关的操作方法。 2. 切片是一种轻量级的数据结构,它有三个属性:指针,长度,容量。这些属性是 Golang 需要操作底层数组的元数据: 切片数据结构的定义: type slice struct { array unsafe.Pointer len int cap int } 上面结构体里的3 个字段分别是指向底层数组的指针、切片访问的元素的个数(即长度)和切片允许增长到的元素个数(即容量)。 3. 切片不需要指定大小。 4. 切片是地址传递。 5. 切片可以痛殴数组来初始化,也可以通过内置函数make()来初始化。初始化时候len = cap,在append等追加元素时候容量不够(cap不足)时候将len扩容2倍。
3. cap()和len()函数的区别 len()返回切片中的元素个数。 cap()返回切片的容量即切片最长可以容纳的元素数量。 package main import "fmt" func main() { var makeSlice = make([]int,3,5) dumpSlice(makeSlice) } func dumpSlice(makeSlice []int){ fmt.Printf("len长度=%d cap长度=%d slice=%v\n",len(makeSlice),cap(makeSlice),makeSlice) } 输出结果: len长度=3 cap长度=5 slice=[0 0 0]
4. 创建切片slice几种方式 // 直接声明 var slice []int // make的方式 var makeSlice1 = make([]int,3,5) // 创建一个类型为 int,长度为 3,容量为 5 的切片 var makeSlice2 = make([]int,3) // 不指定容量,默认容量等于初始时的长度 // 字面量方式 var strSlice = []int{1,2,3,4,5} // 从数组中截取 var array = [...]int{1, 2, 3, 4, 5, 6} myslice := array[1:4]
5. map 是无序的吗? 是的。看下面代码 m:= map[string]string{"1":"aaa","2":"bbb","3":"ccc","4":"ddd","5":"eee"} for k, v := range m { log.Printf("k: %v, v: %v", k, v) } 打印出来结果都是随机无序的。 如何变成有序的输出? 可以先将key进行索引后,在使用sort排序key,然后在根据排序好的索引进行打印输出。 m:= map[string]string{"1":"aaa","2":"bbb","3":"ccc","4":"ddd","5":"eee"} var keys [] string for k := range m{ keys = append(keys,k) } fmt.Println(keys,len(keys)) sort.Strings(keys)//排序切片key for _,val := range keys{ //循环key取值 fmt.Println(m[val]) } 上面使用了sort.Strings排序,对于golang中的排序 go语言对于 int 、 float64 和 string 数组或是分片的排序, go 分别提供了
6. 如何倒叙一个数组 使用sort提供的一些方法 import ( "fmt" "sort" ) var s []int func main() { s := []int{5, 2, 6, 3, 1, 4} sort.Sort(sort.Reverse(sort.IntSlice(s))) fmt.Println(s) } 打印结果: [1 2 3 4 5 6]
7. make和new的区别 分别看下make和new的定义 make: // The make built-in function allocates and initializes an object of type // slice, map, or chan (only). Like new, the first argument is a type, not a // value. Unlike new, make's return type is the same as the type of its // argument, not a pointer to it. The specification of the result depends on // the type: // Slice: The size specifies the length. The capacity of the slice is // equal to its length. A second integer argument may be provided to // specify a different capacity; it must be no smaller than the // length, so make([]int, 0, 10) allocates a slice of length 0 and // capacity 10. // Map: An empty map is allocated with enough space to hold the // specified number of elements. The size may be omitted, in which case // a small starting size is allocated. // Channel: The channel's buffer is initialized with the specified // buffer capacity. If zero, or the size is omitted, the channel is // unbuffered. func make(t Type, size ...IntegerType) Type new: // The new built-in function allocates memory. The first argument is a type, // not a value, and the value returned is a pointer to a newly // allocated zero value of that type. func new(Type) *Type 1. 从入参看,new 函数只接受一个参数,这个参数是一个类型,并且返回一个指向该类型内存地址的指针,make接受参数是两个。 2. make只能创建内建类型(slice、map、chan),因为对于引用类型的变量,不光要声明它,还要为它分配内容空间,同时返回这三个引用类型本身,并且初始化。 new则是可以对所有类型进行内存分配,返回的是指向类型的指针。 看下面代码 var i *int *i=10 fmt.Println(*i) 输出结果报错。
如果使用new方式修改,如下 var i *int i=new(int) *i=10 fmt.Println(*i) 打印就是对的。 3. new返回指针, make 返回引用。 4. new初始化零值, make初始化非零值。
8. uint,int,int8, int16,int32, int64的区别 查看下面代码所打印的结果 var i1 int = 1 var i2 int8 = 2 var i3 int16 = 3 var i4 int32 = 4 var i5 int64 = 5 var i6 uint = 6 fmt.Println("int类型的大小=",unsafe.Sizeof(i1)) fmt.Println("int8类型大小=",unsafe.Sizeof(i2)) fmt.Println("int16类型大小=",unsafe.Sizeof(i3)) fmt.Println("int32类型大小=",unsafe.Sizeof(i4)) fmt.Println("int64类型大小=",unsafe.Sizeof(i5)) fmt.Println("uint类型大小=",unsafe.Sizeof(i6))
int包括有符号整型或无符号整型。 uint和uint8等都属于无符号int类型。 范围大小列表
9. sprintf、fprintf和printf有什么区别
10. nil 切片和空切片区别
|
请发表评论