go入门4---数据

1.Array

数组或者列表属于值类型,赋值和传参会赋值整个数组,而不是指针

看一组数据区别,

共同点:地址都发生了变化,因此在进行传参时会进行复制,

不同点:如果数组指定长度(这个叫数组),那么在进行调用的时候并赋值的时候,原数据不变

    如果未指定长度(这个叫切片),那么在进行复制的时候,就会把原数组的值得地址进行传递,这样在改变值地址对应的值时,原数组对应的值也就会发生变化。

func test(x []int){
   fmt.Printf("test: %p \n", &x)
   fmt.Printf("test 值: %p \n", x)
   x[1] = 10
}
func main() {
   var s = []int{1,2,3}
   test(s)
   fmt.Println(s)
   fmt.Printf("main: %p \n", &s)
   fmt.Printf("main 值: %p \n", s)
}
test: 0xc000096020 
test 值: 0xc000098000 
[1 10 3]
main: 0xc000096000 
main 值: 0xc000098000
func test(x [3]int){
   fmt.Printf("test: %p \n", &x)
   fmt.Printf("test 值: %p \n", x)
   x[1] = 10
}
func main() {
   var s = [3]int{1,2,3}
   test(s)
   fmt.Println(s)
   fmt.Printf("main: %p \n", &s)
   fmt.Printf("main 值: %p \n", s)
}
test: 0xc000096020 
test 值: %!p([3]int=[1 2 3]) 
[1 2 3]
main: 0xc000096000 
main 值: %!p([3]int=[1 2 3]

使用len以及cap都可以计算数组长度

2.切片

len代表切片的可用长度,cap代表切片的最大扩张容量,因此len() <= cap(),读写操作不能超过len,否则会报错,cap的作用是在对切片扩容时,来为切片进行分配空间大小

如第一篇讲到,可以使用make以及new来创建新切片

s := make([]int, 6. 8)  // len 6 cap 8
s := make([]int, 6)  // len 6 cap 6

当对数组进行切片时,它是用过内部指针以和相关属性引用的数组片段,因此改变切片,会对数组造成相应的影响

一个切片是一个数组片段的描述。它包含了指向数组的指针,片段的长度, 和容量(片段的最大长度)。

使用 make([]byte, 5) 创建的切片变量 s 的结构如下:

长度是切片引用的元素数目。容量是底层数组的元素数目(从切片指针开始)

从上述图片可以看出,切片就是引用原来的数组片段,因此对切片再次进行切片,依然会影响原数组

func main() {
    var s = [10]int{1,2,3,4,5,6,7,8,9,0}
    a := s[1:4]
    b := a[1:2]
    b[0] = 1000
    fmt.Println(s) // [1 2 1000 4 5 6 7 8 9 0]
}

这个就是对切片扩容时,因为cap的长度满足扩容大小,因此原数组发生变化,但是如果超出cap限制,底层数组就会重新分配,原数组不会受到影响

func main() {
var data = [10]int{1,2,3,4,5,6,7,8,9,0}
s := data[1:3]
fmt.Println(cap(s), len(s)) // 9 2
s2 := append(s, 100, 200,300,400,500,600,700) // 添加多个值。
fmt.Println(data) // [1 2 3 100 200 300 400 500 600 700]
fmt.Println(s) // [2 3]
fmt.Println(s2) // [2 3 100 200 300 400 500 600 700]
fmt.Println(&s2[2], &data[3]) // 0xc000022108 0xc000022108
s3 := data[1:2:3]
fmt.Println(cap(s3), len(s3)) // 2 1
s4 := append(s3, 1000,2000,3000)
fmt.Println(data) // [1 2 3 100 200 300 400 500 600 700]
fmt.Println(s3) // [2]
fmt.Println(s4) // [2 1000 2000 3000]
fmt.Println(&s4[0], &data[1]) // 0xc00008c020 0xc000082008
}

3.map

哈希表,其实就是python中的字典

键必须是支持相等运算符的类型,例如number,string,pointer,array,struct,interface,值可以是任意

可以使用v,ok := m[键] 来判断是否存在该值。

另外,如果m[不存在的键]不会报错,直接返回空值,删除不存在的也不会报错

map的长度可以使用len测量

for range循环时,可以只取键或者键跟值,每次取的顺序都是随机的

func main() {
m := map[[1]int]string{
[1]int{1} : "s",
[1]int{3} : "sss",
[1]int{4} : "ssss",
[1]int{5} : "sssss",
[1]int{6} : "ssssss",
[1]int{7} : "sssssss",
}
fmt.Println(m) // map[[1]:s [3]:sss [4]:ssss [5]:sssss [6]:ssssss [7]:sssssss]
if v,ok := m[[1]int{1}]; ok {
fmt.Println(v, ok) // s true
}
fmt.Println(m[[1]int{2}]) // ""
fmt.Println(len(m)) // 6
for key, value := range m {
fmt.Println(key, value) // 随机顺序返回,每次不相同
}
for key := range m {
fmt.Println(key) // 随机顺序返回key也就是键,每次不相同
}
}

4.struct

如同前文所说,定义结构体

结构体支持相等操作符,支持匿名结构

type 类型名 struct {}  建议类型名首字母大写,在对struct进行顺序赋值的时候,必须包含全部字段,否则会报错,但是使用关键字进行赋值,则没问题,未赋值的默认为空值

func main() {
    type Mm struct {
        Id int
        Id2 int
    }
    m := Mm{Id:1}
    fmt.Println(m)  // {1 0}
}
func main() {
    type File struct {
        name string
        size int
        attr struct {
            perm int
            owner int }
    }
    f := File{
        name: "test.txt",
        size: 1025,
    }
    f.attr.owner = 1
    f.attr.perm = 755
    fmt.Println(f)   // {test.txt 1025 {755 1}}
    var attr = struct {
        perm  int
        owner int
    }{2, 2222}
    f.attr = attr
    fmt.Println(f)  // {test.txt 1025 {2 2222}}
}

结构体中的匿名字段,一般对于结构体来讲,如果变量名称与类型名称同名,则可以省略类型名称,算是一个语法糖

可以像访问普通字段一样访问匿名成员,编译器会从外部逐层去找所有层次的匿名字段,因此a.id其实就是a.User.id,但是同层次只可以出现一个这样的字段,否则编译器就会凌乱,然后报错,因此一般如果分不清建议使用显示的字段名。

外层同名字段会遮蔽潜入字段名

    type User struct {
        id int
    }
    type Admin struct {
        User
        name string
    }
    a := Admin{}
    a.id =1
    a.name = "google"
    fmt.Println(a)  // {{1} google}    
func main() {
type User struct {
id int
}
type Admin struct {
User
id int
name string
}
a := Admin{}
a.id =1
a.name = "google"
fmt.Println(a) // {{0} 1 google}
a.User.id = 2
fmt.Println(a) // {{2} 1 google}
}

猜你喜欢

转载自www.cnblogs.com/yangshixiong/p/12123760.html
今日推荐