zoukankan      html  css  js  c++  java
  • go入门4---数据

    1.Array

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

    看一组数据区别,

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

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

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

    func test(x []int){
       fmt.Printf("test: %p 
    ", &x)
       fmt.Printf("test 值: %p 
    ", x)
       x[1] = 10
    }
    func main() {
       var s = []int{1,2,3}
       test(s)
       fmt.Println(s)
       fmt.Printf("main: %p 
    ", &s)
       fmt.Printf("main 值: %p 
    ", s)
    }
    test: 0xc000096020 
    test 值: 0xc000098000 
    [1 10 3]
    main: 0xc000096000 
    main 值: 0xc000098000
    func test(x [3]int){
       fmt.Printf("test: %p 
    ", &x)
       fmt.Printf("test 值: %p 
    ", x)
       x[1] = 10
    }
    func main() {
       var s = [3]int{1,2,3}
       test(s)
       fmt.Println(s)
       fmt.Printf("main: %p 
    ", &s)
       fmt.Printf("main 值: %p 
    ", 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}
    }
  • 相关阅读:
    元数据 缓存 池 模式
    ContractPattern 面向面向契约模式
    第三方登录 ----转载自简书,作者 <<碧霄问鼎>>
    证书那些事
    导航(NavanavigationController)push和pop
    iOS app上传错误集锦(转载)
    Block 的基本用法
    正则表达式的用法 转载
    UIView
    UIDate(时间)
  • 原文地址:https://www.cnblogs.com/yangshixiong/p/12123760.html
Copyright © 2011-2022 走看看