go-常识补充-切片-map(类似字典)-字符串-指针-结构体(代码片段)

suwanbin suwanbin     2023-05-05     705

关键词:

Go 常识补充

Go 命名

名字首字母大写可以在外部引用,如果是小写则不能(结构体里面的变量名也是)

打印变量类型科普

fmt.Printf("%T", a) ,注意,用的是 fmt.Printf 函数,a 指的是要查看类型的变量

package main

import "fmt"

func main() 
    fmt.Printf("%T", "asfasf")
    //string

_ 关键字

_ 关键字可以用来占位,把不需要的值赋给它(有点像 python 解压赋值,把不需要的值扔给 _

命名规范相关

  • go 没有规定变量 或 函数名的命名规范是驼峰体还是下划线,文件名推荐使用下划线

  • 不过一般命名都是用驼峰体(不然要暴露给外界的首字母要大写,你后面又小写,就很恶心了 Color_of_bottle

包目录规范

所有的包都必须在 gopath 路径下的 src 文件夹下

  • 目前 go 的包管理还不是很成熟,如果依赖了第三方包的不同版本,会不能兼容(只能有一个版本)

    如果非要兼容两个版本,开发的时候可以暂时先把 gopath 改一下,这样就可以放另一个版本了

Go 语言架构

GOPATH 的工作区包含 bin、src 和 pkg(没有这三个文件夹时需要自己创建)

  • src ------- 源码(包含第三方的和自己项目的)
  • bin ------- 编译生成的可执行程序
  • pkg ------ 编译时生成的对象文件

切片

切片就是对数组的一个引用,其相对数组更灵活一点

切片的长度是切片中的元素数。

切片的容量是从创建切片索引(位置)开始的底层数组中元素数。

1)切片本身不拥有任何数组,只是对现有数组的引用

  • 其实就是一个内存地址,指向某个地方

2)切片的原则是前闭后开

package main

import "fmt"

func main() 
    var a = [8]int1, 2, 3, 4, 5, 6, 7, 8
    // 1)利用数组来创建切片
    // 切片,前闭后开,这里取的是第3到第6个,但是第6个没取到
    var b []int = a[2:5]
    fmt.Println(b)
    //[3 4 5]

    // 2)用 make 来创建切片,第二个参数5是切片长度,第三个参数6是容量
    i := make([]int, 5, 6)
    fmt.Println(i)
    //[0 0 0 0 0]

    // 切片只是对数组的一个引用,指向的是该数组
    a[3] = 111
    fmt.Println(a)
    fmt.Println(b)
    //[1 2 3 111 5 6 7 8]
    //[3 111 5]

    b[0] = 222
    fmt.Println(a)
    fmt.Println(b)
    //[1 2 222 111 5 6 7 8]
    //[222 111 5]

3)切片没有步长这么一说(别和 python 的列表切片搞混了)

4)切片的空值是 nil(虽然打印出来是 []

  • go 里所有的引用类型的空值是 nil

5)切片依附于底层数组,底层数组修改会影响切片,切片修改也会影响底层数组

  • 切片可以通过 内置函数 append() 来扩容,如果超过了切片的长度,切片会自动扩容,申请一个新的数组,变为原来切片容量的两倍,然后与原来的底层数组断开依附,关联新的这个数组(在没有超长扩容时,依旧会与定义时的底层数组相关联)

6)切片要修改值,直接改索引对应的值就行了(会影响到依附的数组)

package main

import "fmt"

func main() 
    var a [8]int = [8]int1, 2, 3, 4, 5, 6, 7, 8
    var b []int = a[2:5]
    fmt.Println(len(b))
    fmt.Println(cap(b))
    //3
    //6

    // 内置函数 append
    b = append(b, 555)
    fmt.Println(b)
    fmt.Println(a)
    //[3 4 5 555]
    //[1 2 3 4 5 555 7 8]


    b[0] = 1111  // 切片要修改值,直接按索引改就行了
    fmt.Println(a)
    fmt.Println(b)
    //[1 2 1111 4 5 555 7 8]
    //[1111 4 5 555]

    
    
    var e []int = []int1, 2
    fmt.Println(e)
    fmt.Println(len(e))
    fmt.Println(cap(e))
    //[1 2]
    //2
    //2

    e = append(e, 3)
    fmt.Println(e)
    fmt.Println(len(e))
    fmt.Println(cap(e))  // 如果超过了切片的长度,切片会自动扩容,申请一个新的数组,变为原来切片容量的两倍
    //[1 2 3]
    //3
    //4

    e[2] = 99  // 切片要修改值,直接改索引对应的值就行了
    fmt.Println(e)
    fmt.Println(len(e))
    fmt.Println(cap(e))
    //[1 2 99]
    //3
    //4

7)切片作为函数参数传递

  • go 参数传递是 copy 传递,所以传过去也是引用,改动会影响原来的数组(间接又影响那个切片)

多维切片

package main

import "fmt"

func main() 
    // 多维切片
    var a [][]string = make([][]string, 2, 3)
    fmt.Println(a[0])
    //[]
    //a[0] = make([]string, 2, 3)  // 定义了下面就不会打印 a[0] == nil 了
    if a[0] == nil 
        fmt.Println("a[0] == nil")
    
    //a[0] == nil

切片初始化的方法

package main

import "fmt"

func main() 
    var a []int = []int1,2,3
    fmt.Println(a)
    fmt.Println(len(a))
    fmt.Println(cap(a))
    //[1 2 3]
    //3
    //3

多维切片初始化

二维切片只能放切片类型 a[0] = "xxx" => a[0][1] = "8787

package main

import "fmt"

func main() 
    // 多维切片初始化
    var a [][]string = [][]string"1", "2", "3", "4"
    fmt.Println(a)
    fmt.Println(len(a))
    fmt.Println(cap(a))
    a[0][1] = "999"
    fmt.Println(a)
    //[[1 2] [3 4]]
    //2
    //2
    //[[1 999] [3 4]]

6)索引只能取长度范围内的索引,(容量比长度大)要操作容量的,要用 append() 内置方法

切片删除元素(会略微影响效率 ,少用)

跳过了某些元素(即便是这样,也比 python 的效率还要高得多)

package main

import "fmt"

func main() 
    var a = []int1, 2, 3, 4, 5, 6
    fmt.Println(a)
    //[1 2 3 4 5 6]

    // 删除第三个元素
    a = append(a[0:2], a[3:]...)  // 前开后闭原则,索引为2的元素(即第三个元素)被忽略掉了
    fmt.Println(a)
    //[1 2 4 5 6]

copy 函数

可以用来把一个切片 copy 到另一个切片上,然后就可以回收底层数组占用的内存

  • 比如一个切片:容量是10000,长度为3,浪费内存
  • 此时把它 copy 到另一个切片上,让 go 的垃圾回收机制自动取回收不用的内存(那个没用的切片)
  • copy 过去的那个切片对应的底层数组又是一个新的了,所以 copy 过的切片不会影响之前那个切片

需要 copy 到的切片,长度比要 copy 的切片长就 copy 过来,短就丢掉超了的那部分

package main

import "fmt"

func main() 
    // 创建一个长度为3,容量为10000的切片
    var a = make([]int, 3, 10000)
    a[1] = 99
    a[2] = 888
    fmt.Println(a)
    //[0 99 888]

    // 创建一个长度为2,容量为4的切片
    var b = make([]int, 2, 4)
    fmt.Println(b)
    //[0 0]

    copy(b, a)  // 把 a 拷贝给 b (右边的拷贝给左边)
    fmt.Println(b)
    //[0 99]


    var c = make([]int, 5, 10000)
    c[1] = 2
    c[3] = 4
    //c[9] = 9  // 会报错,超过 c 的长度了(虽然容量还够的-->要想加用内置函数 append)
    fmt.Println(c)
    //[0 2 0 4 0]
    var d = make([]int, 2)
    fmt.Println(d)
    //[0 0]
    copy(d, c)  // 把 c 拷贝给 d (右边的拷贝给左边)
    fmt.Println(d)
    //[0 2]  //超出长度的就丢弃掉了
    fmt.Println(c)
    //[0 2 0 4 0]

打散切片

package main

import "fmt"

func main() 
    a := [8]int1,2,3,4,5,6,7,8
    b := a[:]  // 取一个内容和 a 数组一模一样的切片
    fmt.Println(b)
    //[1 2 3 4 5 6 7 8]

    printGTE6(b)
    //下面将返回大于等于6的元素
    //6
    //7
    //8

    printGTE7(1,2,34,5,6,8)
    //下面将返回大于等于7的元素
    //34
    //8
    printGTE7(b...)  // 可以利用 ... 将切片打散成一个个参数传递
    //下面将返回大于等于7的元素
    //7
    //8


func printGTE6(a []int)  
    // 一个函数,接收一个数组,打印出大于等于6的元素
    fmt.Println("下面将返回大于等于6的元素")
    for _, v := range a
        if v >= 6 
            fmt.Println(v)
        
    


func printGTE7(a ...int)  
    // 一个函数,接收一堆参数,打印出大于等于7的那几个参数
    fmt.Println("下面将返回大于等于7的元素")
    for _, v := range a
        if v >= 7 
            fmt.Println(v)
        
    

循环打印多维切片

package main

import "fmt"

func main() 
    pls := [][]string
        "C", "C++",
        "JavaScript",
        "Go", "Rust",
    
    fmt.Println(pls)
    //[[C C++] [JavaScript] [Go Rust]]

    // 遍历打印多维切片
    for _, v := range pls 
        for _,v1 := range v
            fmt.Println(v1)
        
    
    //C
    //C++
    //JavaScript
    //Go
    //Rust

Map (类似 python 字典)

类似于 python 中的字典

1)go 是强类型语言,所以 maps 的 key 和 value 类型都是固定的

2)map 的空值是 nil 类型(说明它也是引用类型)(赋了初值就不是 nil 了)

3)map 的赋值

map 定义及初始化

package main

import "fmt"

func main() 
    // map 定义
    //var 变量名 map[键类型]值类型
    var a map[string]string
    fmt.Println(a)
    if a == nil 
        fmt.Println("a == nil")
    
    //map[]
    //a == nil

    // map 的初始化
    var b map[int]string = make(map[int]string)
    fmt.Println(b)
    if b == nil 
        fmt.Println("b == nil")
    
    //map[]

    // 定义和初始化的方式二
    var c = map[int]string1: "10", 2: "20"
    fmt.Println(c)
    //map[1:10 2:20]


赋值、取值、改值

4)取的 key 不存在就会返回 值类型的零值(string “”、int 0、bool false)

5)map 取值时,有两个返回值,第二个值一般取名 okok 的值为 true 表示该键存在,false 表示该键不存在

package main

import "fmt"

func main() 
    // map 的赋值、取值、改值
    goods := map[string]uint8"apple": 3, "bear": 2
    fmt.Println(goods)
    //map[apple:3 bear:2]

    goods["milk"] = 4
    fmt.Println(goods)
    //map[apple:3 bear:2 milk:4]
    fmt.Println(goods["milk"])  // 取值
    //4


    goods["apple"] = 5  // 修改值
    fmt.Println(goods["apple"])
    fmt.Println(goods)
    //5
    //map[apple:5 bear:2 milk:4]

    fmt.Println(goods["laptop"])
    //0  // 因为 goods 这个 map 值的类型是 int,取不到键对应的值时,会默认返回值的零值 int 即 0

    // 那么怎么知道这个键到底存不存在呢?万一那个值凑巧等于值类型的零值呢?
    count, ok := goods["laptop"]
    fmt.Println(count, ok)
    //0 false  // ok 是 false,表示 map 中无该键 laptop,然后会把 count 赋值为 map 值类型的零值,int 类型即 0

    count, ok = goods["apple"]
    fmt.Println(count, ok)
    //5 true  // ok 是 true,表示 map 中有该键 apple,然后会把 count 赋值为 map 中该键对应的值

    if v, okLaptop := goods["laptop"]; okLaptop
        fmt.Println("goods 中存在 laptop,有", v, "个")
    else 
        fmt.Println("goods 中不存在 laptop")
    
    //goods 中不存在 laptop

map 删除元素、参数传递

内置函数 delete()

6)删值用 内置函数 delete() 该函数没有返回值,删不存在的也不会报错(只管删,不管你 map 里原来有没有该键)

7)map 是引用类型,作为参数传给函数,改变了会影响到外部的那个 map(是引用)

package main

import "fmt"

func main() 
    // map 的删值
    shopcart := map[string]string"15411231": "小米电视机", "15115134": "小米9"
    fmt.Println(shopcart)
    //map[15115134:小米9 15411231:小米电视机]

    //fmt.Println(delete(shopcart, "15411231"))  // 这个语句会直接报错,因为 delete 没有返回值,也不能被接收(包括打印)

    delete(shopcart, "15411231")
    fmt.Println(shopcart)
    //map[15115134:小米9]

    // map 的长度
    fmt.Println(shopcart)
    fmt.Println(len(shopcart))
    //map[15115134:小米9]
    //  //1

    // map 是值类型还是引用类型?作为函数参数传递后,在函数内部修改是否会影响原来的 map?
    testMap(shopcart)
    //map[15115134:小米9]
    //map[12221231:小米手环 15115134:小米9]
    fmt.Println(shopcart)
    //map[12221231:小米手环 15115134:小米9]
    // => map 是引用类型,会影响原来的 map


func testMap(shopcart map[string]string)  
    fmt.Println(shopcart)
    shopcart["12221231"] = "小米手环"
    fmt.Println(shopcart)

map 相等比较、循环遍历

8)map 之间不能直接 == 比较,只能直接和 nil 比,要实在想比较两个 map,可以自定义规则遍历去比较

9)map 是无序的

10)map 的键的类型必须是可 hash 的

package main

import "fmt"

func main() 
    // map 的相等比较
    goodPrice := map[string]float32"apple": 13.5, "one plus 8": 3899
    var goodPrice2 map[string]float32
    //if goodPrice == goodPrice2  // 直接就报错,map 之间不能直接比较
    //
    //
    if goodPrice == nil   // map 可以和 nil 比较
        fmt.Println("goodPrice == nil")
    
    if goodPrice2 == nil 
        fmt.Println("goodPrice2 == nil")
    
    //goodPrice2 == nil

    // 循环出 map 中的所有元素
    fmt.Println(goodPrice)
    for k, v := range goodPrice   // 这里拿出的 key 不是索引,而是 map 的键
        fmt.Println(k, v)
    
    //map[apple:13.5 one plus 8:3899]
    //apple 13.5  //这一行和下一行的打印顺序不是固定的(因为 map 是无序的)
    //one plus 8 3899

    //goodPrice3 := map[[]int]string[]int1,3,4: "123"  // 直接报错,map 的 key 必须是可 hash 的

字符串

字符串的定义、长度、遍历字节、字符

1)两种方式 双引号 "" 反引号 ``` `

2)在 go 中,一个中文字符占 3 个字节长度,英文字母与数字均为1个字节长度

  • 在 go 中 string 类型采用 utf-8 编码,每个中文字符占 3 个字节,英文字母、数字、常见符号占 1 个字节
  • 其他语言中是 unicode 编码,unicode 统一用2Bytes(16 bit) 表示所有字符(有关编码的知识可以参考我的博客

3)用 utf8.RuneCountInString(name) 来统计字符串长度,内置方法 len() 统计的是字节数

4)字符串是个只读切片

可以索引取值(取到的是数字码,用 string 括起来可以变成字符),但是不能改它的值(只读)

5)byte 就是 uint8 的别名、rune 是 int32 的别名,在字符串里分别代表字节、字符

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() 
    // 字符串的定义有两种
    var s1 = "i'm s1"     // 双引号的定义方式
    var s2 = `i'
am
    s2` // 反引号的定义方式,可以是多行

    fmt.Println(s1)
    //i'm s1
    fmt.Println(s2)
    //i'
    //am
    //  s2

    // 字符串的长度
    var str1 = "i am is a string 啊."
    fmt.Println(len(str1)) // len 获取到的是字符串的字节长度
    //21
    fmt.Println(utf8.RuneCountInString(str1)) // utf8.RuneCountInString 获取到的是字符个数
    //19

    // 字符串是一个只读切片
    fmt.Println(str1)
    fmt.Println(str1[0], string(str1[0]))
    //i am is a string 啊.
    //105 i

    //str1[0] = 213  // 会直接报错,不能更改字符串 (字符串是个只读切片)

    // 遍历字符串
    str2 := "1测2s"

    for i := 0; i < len(str2); i++ 
        fmt.Printf("%T ", str2[i])
        fmt.Println(i, str2[i], string(str2[i]))
    
    //uint8 0 49 1  // int8 即 byte,代表取的是一个字节
    //uint8 1 230 ?
    //uint8 2 181 μ
    //uint8 3 139 ?
    //uint8 4 50 2
    //uint8 5 115 s

    for i, v := range str2 
        fmt.Printf("%T ", v)
        fmt.Println(i, v, string(v))
    
    //int32 0 49 1  // int32 即 rune,代表取的是一个字符
    //int32 1 27979 测
    //int32 4 50 2
    //int32 5 115 s


    // 利用切片合成字符串
    byteSlice := []byte0x43, 0x61, 0x66, 0xc3, 0xA9
    strByByte := string(byteSlice)
    fmt.Println(byteSlice)
    //[67 97 102 195 169]
    fmt.Println(strByByte)
    //Café
    charlen := len(strByByte)
    charCount := utf8.RuneCountInString(strByByte)
    fmt.Println(charlen, charCount)
    //5 4

指针

1)指针是一种存储变量内存地址的变量

2)& 为取址符,可以取到后面变量的内存

3)*放在内存地址前面可以取到该内存地址所对应的值

4)指针也有类型,指定了类型就不能再指向其他类型了

5)*放在类型前面可以表示指向该类型的一个指针

指向什么类型就在什么类型前面加 **int

6)指针的零值是 nil

var a *int --> nil

package main

import "fmt"

func main()  
    a := 10
    fmt.Println(&a)  // 1)& 为取址符,可以取到后面变量的内存地址
    //0xc00000a0b8
    fmt.Println(*&a)  // 2)*放在内存地址前面可以取到该内存地址所对应的值
    //10

    b := &a  // 等价于 var b *int = &a
    // 3)*放在类型前面可以表示指向该类型的一个指针
    fmt.Println(b)
    //0xc00005e090
    fmt.Println(*b)
    //10

    //c := "dsadasd"
    //b = &c  // 会直接报错,因为 b 指针在定义时就指向了 int 类型,现在要指向的是 string 类型,和他不是同一个类型了
    
    var e *int
    fmt.Println(e)
    if e == nil
        fmt.Println("e == nil")
    
    //<nil>
    //e == nil

向函数传递指针参数

用了指针做参数传递,可以不考虑函数参数的传递是值传递还是引用传递(拿着内存地址,直接就能改了)

7)拿指针来传递参数,修改指针会将其指向的变量一同修改

package main

import "fmt"

func main()  
    a := 10
    b := &a

    fmt.Println(a)
    //10
    changePoint(b)  // 利用指针去修改值
    fmt.Println(a)
    //11

    fmt.Println(a)
    //11
    changeNum(*b)
    fmt.Println(a)
    //11


func changePoint(point *int)  
    *point++  // 指针会更改指向内存地址上的值


func changeNum(num int)  
    num++

传递数组指针 (最好是用切片)

8)指针也可以传递数组,但最好还是使用切片来传递数组

用切片做函数参数可以不用指定切片大小,而用指针做函数参数需要指定指针指向类型(数组类型需要指定大小)

package main

import "fmt"

func main() 
    a := [5]int1, 2, 3, 4, 5
    aPoint := &a
    ArgPoint(aPoint)
    //[999 2 3 4 5]

    aSlice := a[:]
    ArgSlice(aSlice)
    //[888 2 3 4 5]

func ArgPoint(point *[5]int)   // 如果使用 指针 做函数参数,需要指定指针所指定类型的大小,很不方便
    (*point)[0] = 999
    fmt.Println(*point)


func ArgSlice(slice []int)   // 如果是用 切片 做函数参数,则不需要关心该参数的大小
    slice[0] = 888
    fmt.Println(slice)


// 所以,我们优先选择用切片来当做函数参数,而不是指针!

9)Go 不支持指针运算

指针运算很危险,用不好会闪退,内存溢出等

结构体

go 可以说有面向对象,也可以说没有面向对象(作者说,你觉得有就有,你觉得没有就没有)

1)结构体是一系列属性的集合(没有方法)

结构体零值

2)结构体是值类型

3)结构体的属性也是无序的

4)初始化可以指名道姓地传(指名道姓可以少传),也可以按位置传(必须所有属性都传)

package main

import "fmt"

//type 结构体名 struct 
//  属性名1 属性名1的类型
//  属性名2 属性名2的类型
//  属性名3 属性名3的类型
//
type Person struct 
    name string
    //sex, age int  // 是下面两行的简写
    sex int
    age int

func main()  
    person := Person  // 等价于 var person Person = Person
    fmt.Println(person)
    fmt.Println(person.name)
    fmt.Println(person.sex)
    // 0 0
    //  // 这是空字符串,不是没值(因为 string 类型的零值是 "" 空字符串)
    //0

    var person2 Person = Personname: "swb"  // 初始化可以指名道姓地传(指名道姓可以少传)
    var person3 Person = Person"swb", 1, 18  // 也可以按位置传(必须所有属性都传)

    fmt.Println(person2)
    //swb 0 0
    fmt.Println(person3)
    //swb 1 18

    // 取属性、修改属性
    fmt.Println(person2.name)
    //swb
    person2.age = 66
    fmt.Println(person2.age)
    //66

匿名结构体

5)匿名结构体定义完了必须 立马实例化并赋值给一个对象

package main

import "fmt"

func main()  
    a := struct 
        name string
        age int
    "swb", 18
    fmt.Println(a.name)
    //swb

结构体指针

6)可以直接用地址点属性(官方做了处理)

package main

import "fmt"

type Person struct 
    name string
    //sex, age int  // 是下面两行的简写
    sex int
    age int


func main() 
    p := Personname: "swb"
    var pPoint *Person = &p
    fmt.Println(pPoint)
    //&swb 0 0  // 这其实是一种 显示 优化,让我们知道内存地址存的是啥
    fmt.Println((*pPoint).name)
    //swb
    fmt.Println(pPoint.name)  // 结构体指针做了优化,可以直接用结构体指针 点 结构体属性 => pPoint.name
    //swb

结构体匿名字段

package main

import "fmt"

// 结构体匿名字段
type Person struct 
    string
    int
    //age int  // 如果有两个 int 类型的属性,可以这么弄


func main()  
    //p := Person"swb", 19
    p := Personstring: "swb", int: 19  // 匿名字段的属性内名也可以用作 键

    fmt.Println(p.string)
    //swb

很奇葩,但是有用处,可以用作变量提升

表示字段没有名字

p := Person

结构体嵌套

package main

import "fmt"

// 结构体嵌套
type Person struct 
    name     string
    sex, age int
    hobby    Hobby


type Hobby struct 
    id   int
    name string


func main() 
    p := Person
    fmt.Println(p)
    // 0 0 0   // 零值状态,依旧是取该类型的零值 => "" 0 0 0 "" 字符串类型的零值是 "" 打印的时候,看不出来

    p2 := Personname: "swb", hobby: Hobbyid: 1, name: "学习"
    fmt.Println(p2.hobby.name)
    //学习
    fmt.Println(p2)
    //swb 0 0 1 学习

结构体嵌套 + 匿名字段

package main

import "fmt"

// 结构体嵌套 + 匿名字段 --> 变量提升
type Person struct 
    name     string
    sex, age int
    Hobby


type Hobby struct 
    id   int
    name string


func main() 
    p := Person
    fmt.Println(p)
    // 0 0 0   // 零值状态,依旧是取该类型的零值 => "" 0 0 0 "" 字符串类型的零值是 "" 打印的时候,看不出来

    p2 := Personname: "swb", Hobby: Hobbyid: 1, name: "学习"
    fmt.Println(p2.Hobby.name)  // 重名变量,不提升
    //学习
    fmt.Println(p2.id)  // 可以直接取到 Hobby 中的 id,变量 id 被提升了
    //1
    fmt.Println(p2)
    //swb 0 0 1 学习

7)变量提升过程中,如果有重名的,(重名的那个变量)就不提升了

(有点 python 中的继承)

结构体相等比较

结构体之间可不可以比较要根据里面字段来的,里面字段都可以比较,那就可以比较(比如里面有切片字段,那就不可比较了)

作业

把 map 做成有序的

go语言基础:map|函数(代码片段)

...数类型的简写可变参数返回值多返回值返回值命名返回值补充变量作用域全局变量局部变量函数类型与变量定义函数类型函数类型变量使用高级用法函数作为参数函数作为返回值匿名函数mapmap类似与python中的字典ÿ 查看详情

go语言字典和结构体(代码片段)

...典、映射)map翻译过来就是字典或者映射,可以把map看做是切片的升级版切片是用来存储一组相同类型的数据的,map也是用来存储一组相同类型的数据的在切片中我们可以通过索引获取对应的元素,在map中我们可以通过key获取对应的... 查看详情

go入门教程2内置基础类型(boolean数值字符串错误类型),分组,iota枚举,array(数值),slice(切片),map(字典),make/new操作,零值

这小节我们将要介绍如何定义变量、常量、Go内置类型以及Go程序设计中的一些技巧。定义变量Go语言里面定义变量有多种方式。使用var关键字是Go最基本的定义变量方式,与C语言不同的是Go把变量类型放在变量名后面://定义一... 查看详情

golangbasic_leaming2语言容器(代码片段)

...。下面这段代码中,定义了一个变量为arr,成员类型为字符串,大小为3的数组:packagemainimport( &# 查看详情

go语言基础切片,map(代码片段)

...切片元素为map类型的切片循环初始化值为切片的mapmap计算字符串每个单词出现的次数切片(Slice)菜鸟教程切片B站李文周go语言教学切片使用packagemainimport"fm 查看详情

go+字典map(代码片段)

...合。他的基本格式是map[key的类型]value的类型,字典和切片比较类似,切片是用索引来进行读写操作的,而字典是用key来进行读写操作的。map的相关使用    我们有两种方式定义map:使用关键字定义。使用make()函... 查看详情

golangbasic_leaming2语言容器(代码片段)

...定义数组Go语言初始化数组Go语言遍历数组参考文献Go语言切片(Slice)初始化_删除元素_遍历什么是切片声明切片使用make()函数构造切片使用append()函数为切片添加元素从数组或切片生成新的切片从指定范围中生成切片重... 查看详情

go语言容器(container)(代码片段)

...个数值条件可以同时查询基于哈希值的多键索引及查询1)字符串转哈希值2)查询键3)构建索引4)查询逻辑完整代码利用map特性的多键索引及查询1)构建索引2)查询逻辑总结完整代码Go语言sync.Map(在并发环境中使用的map)Go语... 查看详情

golang学习五·五:指针&切片&字典&结构体(代码片段)

...数参数:4.1函数传值:4.2例:4.指针使用注意:二、slice--切片:1.切片简述:2.创建slice:2.1声明slice与array的区别:2.2经常使用的创建slice的方法:3.slice操作:3.1切片截取:3.2切片和底层数组关系:3.3切片做函数参数:4.常用操作函数:4.1append函... 查看详情

go-数组-切片-字典(代码片段)

...始。 len是Go语言的内建函数的名称。该函数用于获取字符串、数组、切片、字典或通道类型的值的长度。varlength=len(numbers) 如果我们只声明一个数组类型的变量而不为它赋值,那么该变量的值将会是指定长度的、其中各元... 查看详情

go语言学习笔记—基础—高级数据类型—数据容器—字典map:map声明与初始化(代码片段)

...为map是使用hash表实现的可迭代。我们可以像迭代数组和切片那样,遍历map2.map声明与初始化使用关键字 查看详情

go事一眼看穿go的集合和切片(代码片段)

文章目录⛳️Go集合定义集合Go切片⛳️Go集合在Go中与集合相关的关键字是Map,其表示一种无需的键值对集合,Map可以通过Key检索值,这一点和Python中的字典特别像。集合是无序的,并且使用hash表实现。定义集合... 查看详情

go语言切片map字符串(代码片段)

切片1.什么是切片切片本身不拥有任何数据,它们只是对现有数组的引用。2.切片的定义1.方式1:由数组切出来:var变量名[]元素类型=数组名[开始值:结束值]//1.定义数组vara[8]int=[8]int1,2,3,4,5,6,7,8//2.定义切片,注意[]中没有数字varb[... 查看详情

go基础数组切片map(代码片段)

数组、切片、Map数组、切片、Map数组array切片slice键值对map相关资料数组array格式形如:varvariable_name[SIZE]variable_type注:数组的长度是固定的示例一:基操import"fmt"funcmain() vararr[3]string=[3]string"张三" 查看详情

go中map的创建和初始化(代码片段)

...有的键都是唯一的,而且必须是支持==和!=操作符的类型2)切片、函数以及包含切片的结构类型这些类型由于具有引用语义,不能作为映射的键 查看详情

go语言学习--map类型的切片(代码片段)

今天在项目中遇到了一个切片的map,记录下map切片的使用1packagemain23import"fmt"45funcmain()67//VersionA:8items:=make([]map[string]int,5)9fori:=rangeitems10items[i]=make(map[string]int,1)11items[i]["num"]=i1213fmt.Printf("V 查看详情

go语言范围(range)(代码片段)

...言范围(Range)切片迭代map迭代起始节点就随机了字符串迭代channel结构体golang中数组与切片的区别详析Go切片和Go数组定义切片与数组的区别数组切片代码数组声明与赋值切片声明与初始化值传递与引用传递Go语言范围ÿ... 查看详情

go语言范围(range)(代码片段)

...言范围(Range)切片迭代map迭代起始节点就随机了字符串迭代channel结构体golang中数组与切片的区别详析Go切片和Go数组定义切片与数组的区别数组切片代码数组声明与赋值切片声明与初始化值传递与引用传递Go语言范围ÿ... 查看详情