关于切片操作

知识回顾

new(T) 和 make(T,args) 是 Go 语言内建函数,用来分配内存,但适用的类型不同

new(T) 会为 T 类型的新值分配已置零的内存空间,并返回地址(指针),即类型为 *T 的值。换句话说就是,返回一个指针,该指针指向新分配的、类型为 T 的零值。适用于值类型,如数组、结构体等。

make(T,args) 返回初始化之后的 T 类型的值,这个值并不是 T 类型的零值,也不是指针 *T,是经过初始化之后的 T 的引用。make() 只适用于 slice、map 和 channel.

package main

import "fmt"

func main() {
    s := make([]int,5)
    fmt.Println(len(s))
    fmt.Println(cap(s))
    s = append(s, 1,2,3)
    fmt.Println(s)


    s2 := make([]int, 0)
    fmt.Println(len(s2))
    fmt.Println(cap(s2))
    s2 = append(s2,1,2,3,4)
    fmt.Println(s2)
}

我们通过 make([]int,5) 创建的的s 其实是[0 0 0 0 0 ],而初学者很可能认为是一个空的切片

关于函数返回值

在函数有多个返回值时,只要有一个返回值有命名,其他的也必须命名。如果有多个返回值必须加上括号();如果只有一个返回值且命名也必须加上括号()。

一些题目

package main

import "fmt"


func main() {
    list := new([]int)
    list = append(list,1)
    fmt.Println(list)
}

上述代码是否可以编译通过?

答案是否,解释: new([]int) 之后的list是一个*[]int类型的指针,不能对指针执行append操作,可以使用make()初始化然后执行append 同样的,map 和 channel 建议使用 make() 或字面量的方式初始化,不要用 new()

package main

import "fmt"

func main() {
    s1 := []int{1,2,3}
    s2 := []int{4,5}
    s1 = append(s1,s2)
    fmt.Println(s1)
}

上述代码是否可以编译通过

答案是否,解释: append() 的第二个参数不能直接使用 slice,需使用 … 操作符,将一个切片追加到另一个切片上:append(s1,s2…)。或者直接跟上元素,形如:append(s1,1,2,3)。

package main

import "fmt"

var (
    size := 1024
    max_size = size * 2
)

func main() {
    fmt.Println(size, max_size)
}

上述代码是否可以编译通过

答案是否,解释:

变量声明的简短模式,形如:x := 100。但这种声明方式有限制:

  • 必须使用显示初始化;
  • 不能提供数据类型,编译器会自动推导;
  • 只能在函数内部使用简短模式;

    package main
    
    import "fmt"
    
    func main() {
    sn1 := struct {
        age int
        name string
    }{age:11, name:"aaa"}
    sn2 := struct {
        age int
        name string
    }{age:11, name:"aaa"}
    
    if sn1 == sn2 {
        fmt.Println("s1===s2")
    }
    
    sm1 := struct {
        age int
        m map[string]string
    }{age:23,m: map[string]string{"a":"1"}}
    
    sm2 := struct {
        age int
        m map[string]string
    }{age:23,m: map[string]string{"a":"1"}}
    if sm1 == sm2 {
        fmt.Println("sm1===sm2")
    }
    }
    

上述代码是否可以编译通过

答案是否,解释:

关于结构体的比较:

  • 结构体只能比较是否相等,但是不能比较大小。
  • 相同类型的结构体才能够进行比较,结构体是否相同不但与属性类型有关,还与属性顺序相关,sn3 与 sn1 就是不同的结构体;

    sn3 := struct {
        name string
        age int
    }{age:11, name:"aaa"}
    
  • 如果 struct 的所有成员都可以比较,则该 struct 就可以通过 == 或 != 进行比较是否相等,比较时逐个项进行比较,如果每一项都相等,则两个结构体才相等,否则不相等;

常见的有 bool、数值型、字符、指针、数组等, 像切片、map、函数等是不能比较的