Go官方指南(三)其他类型 struct、slice、映射_go struct指针slice(5)

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

func main() {
var a [2]string
a[0] = “Hello”
a[1] = “World”
fmt.Println(a[0], a[1])
fmt.Println(a)

primes := [6]int{2, 3, 5, 7, 11, 13}
fmt.Println(primes)

}


### 切片


每个数组的大小都是固定的。而切片则为数组元素提供动态大小的、灵活的视角。在实践中,切片比数组更常用。


类型 `[]T` 表示一个元素类型为 `T` 的切片。


切片通过两个下标来界定,即一个上界和一个下界,二者以冒号分隔:



a[low : high]


它会选择一个半开区间,包括第一个元素,但排除最后一个元素。


以下表达式创建了一个切片,它包含 `a` 中下标从 1 到 3 的元素:



a[1:4]



package main

import “fmt”

func main() {
primes := [6]int{2, 3, 5, 7, 11, 13}

var s []int = primes[1:4]
fmt.Println(s)

}


### 切片就像数组的引用


切片并不存储任何数据,它只是描述了底层数组中的一段。


更改切片的元素会修改其底层数组中对应的元素。


与它共享底层数组的切片都会观测到这些修改。



package main

import “fmt”

func main() {
names := [4]string{
“John”,
“Paul”,
“George”,
“Ringo”,
}
fmt.Println(names)

a := names[0:2]
b := names[1:3]
fmt.Println(a, b)

b[0] = "XXX"
fmt.Println(a, b)
fmt.Println(names)

}


### 切片文法


切片文法类似于没有长度的数组文法。


这是一个数组文法:



[3]bool{true, true, false}


下面这样则会创建一个和上面相同的数组,然后构建一个引用了它的切片:



[]bool{true, true, false}



package main

import “fmt”

func main() {
q := []int{2, 3, 5, 7, 11, 13}
fmt.Println(q)

r := []bool{true, false, true, true, false, true}
fmt.Println(r)

s := []struct {
	i int
	b bool
}{
	{2, true},
	{3, false},
	{5, true},
	{7, true},
	{11, false},
	{13, true},
}
fmt.Println(s)

}


### 切片的默认行为


在进行切片时,你可以利用它的默认行为来忽略上下界。


切片下界的默认值为 `0`,上界则是该切片的长度。


对于数组



var a [10]int


来说,以下切片是等价的:



a[0:10]
a[:10]
a[0:]
a[:]



package main

import “fmt”

func main() {
s := []int{2, 3, 5, 7, 11, 13}

s = s[1:4]
fmt.Println(s)

s = s[:2]
fmt.Println(s)

s = s[1:]
fmt.Println(s)

}


### 切片的长度与容量


切片拥有 **长度** 和 **容量**。


切片的长度就是它所包含的元素个数。


切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。


切片 `s` 的长度和容量可通过表达式 `len(s)` 和 `cap(s)` 来获取。


你可以通过重新切片来扩展一个切片,给它提供足够的容量。试着修改示例程序中的切片操作,向外扩展它的容量,看看会发生什么。



package main

import “fmt”

func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)

// 截取切片使其长度为 0
s = s[:0]
printSlice(s)

// 拓展其长度
s = s[:4]
printSlice(s)

// 舍弃前两个值
s = s[2:]
printSlice(s)

}

func printSlice(s []int) {
fmt.Printf(“len=%d cap=%d %v\n”, len(s), cap(s), s)
}


### nil 切片


切片的零值是 `nil`。


nil 切片的长度和容量为 0 且没有底层数组。



package main

import “fmt”

func main() {
var s []int
fmt.Println(s, len(s), cap(s))
if s == nil {
fmt.Println(“nil!”)
}
}


### 用 make 创建切片


切片可以用内建函数 `make` 来创建,这也是你创建动态数组的方式。


`make` 函数会分配一个元素为零值的数组并返回一个引用了它的切片:



a := make([]int, 5) // len(a)=5


要指定它的容量,需向 `make` 传入第三个参数:



b := make([]int, 0, 5) // len(b)=0, cap(b)=5

b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:] // len(b)=4, cap(b)=4



package main

import “fmt”

func main() {
a := make([]int, 5)
printSlice(“a”, a)

b := make([]int, 0, 5)
printSlice("b", b)

c := b[:2]
printSlice("c", c)

d := c[2:5]
printSlice("d", d)

}

func printSlice(s string, x []int) {
fmt.Printf(“%s len=%d cap=%d %v\n”,
s, len(x), cap(x), x)
}


### 切片的切片


切片可包含任何类型,甚至包括其它的切片。



package main

import (
“fmt”
“strings”
)

func main() {
// 创建一个井字板(经典游戏)
board := [][]string{
[]string{“", "”, ““},
[]string{”
”, “", "”},
[]string{“", "”, “_”},
}

// 两个玩家轮流打上 X 和 O
board[0][0] = "X"
board[2][2] = "O"
board[1][2] = "X"
board[1][0] = "O"
board[0][2] = "X"

for i := 0; i < len(board); i++ {
	fmt.Printf("%s\n", strings.Join(board[i], " "))
}

}


### 向切片追加元素


为切片追加新的元素是种常用的操作,为此 Go 提供了内建的 `append` 函数。内建函数的[文档]( )对此函数有详细的介绍。



func append(s []T, vs …T) []T


`append` 的第一个参数 `s` 是一个元素类型为 `T` 的切片,其余类型为 `T` 的值将会追加到该切片的末尾。


`append` 的结果是一个包含原切片所有元素加上新添加元素的切片。


当 `s` 的底层数组太小,不足以容纳所有给定的值时,它就会分配一个更大的数组。返回的切片会指向这个新分配的数组。


(要了解关于切片的更多内容,请阅读文章 [Go 切片:用法和本质]( )。)



package main

import “fmt”

func main() {
var s []int
printSlice(s)

// 添加一个空切片
s = append(s, 0)
printSlice(s)

// 这个切片会按需增长
s = append(s, 1)
printSlice(s)

// 可以一次性添加多个元素
s = append(s, 2, 3, 4)
printSlice(s)

}

func printSlice(s []int) {
fmt.Printf(“len=%d cap=%d %v\n”, len(s), cap(s), s)
}


### Range


`for` 循环的 `range` 形式可遍历切片或映射。


当使用 `for` 循环遍历切片时,每次迭代都会返回两个值。第一个值为当前元素的下标,第二个值为该下标所对应元素的一份副本。



package main

import “fmt”

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
for i, v := range pow {
fmt.Printf(“2**%d = %d\n”, i, v)
}
}


### range(续)


可以将下标或值赋予 `_` 来忽略它。



for i, _ := range pow
for _, value := range pow


若你只需要索引,忽略第二个变量即可。



for i := range pow



package main

import “fmt”

func main() {
pow := make([]int, 10)
for i := range pow {
pow[i] = 1 << uint(i) // == 2**i
}
for _, value := range pow {
fmt.Printf(“%d\n”, value)
}
}


### 练习:切片


实现 `Pic`。它应当返回一个长度为 `dy` 的切片,其中每个元素是一个长度为 `dx`,元素类型为 `uint8` 的切片。当你运行此程序时,它会将每个整数解释为灰度值(好吧,其实是蓝度值)并显示它所对应的图像。


图像的选择由你来定。几个有趣的函数包括 `(x+y)/2`, `x*y`, `x^y`, `x*log(y)` 和 `x%(y+1)`。


(提示:需要使用循环来分配 `[][]uint8` 中的每个 `[]uint8`;请使用 `uint8(intValue)` 在类型之间转换;你可能会用到 `math` 包中的函数。)



package main

import “golang.org/x/tour/pic”

func Pic(dx, dy int) [][]uint8 {
}

func main() {
pic.Show(Pic)
}


### 映射


映射将键映射到值。


映射的零值为 `nil` 。`nil` 映射既没有键,也不能添加键。


`make` 函数会返回给定类型的映射,并将其初始化备用。



package main

import “fmt”

type Vertex struct {
Lat, Long float64
}

var m map[string]Vertex

func main() {
m = make(map[string]Vertex)
m[“Bell Labs”] = Vertex{
40.68433, -74.39967,
}
fmt.Println(m[“Bell Labs”])
}


### 映射的文法


映射的文法与结构体相似,不过必须有键名。



package main

import “fmt”

type Vertex struct {
Lat, Long float64
}

var m = map[string]Vertex{
“Bell Labs”: Vertex{
40.68433, -74.39967,
},
“Google”: Vertex{
37.42202, -122.08408,
},
}

func main() {
fmt.Println(m)
}


### 映射的文法(续)


若顶级类型只是一个类型名,你可以在文法的元素中省略它。



package main

import “fmt”

type Vertex struct {
Lat, Long float64
}

var m = map[string]Vertex{
“Bell Labs”: {40.68433, -74.39967},
“Google”: {37.42202, -122.08408},
}

func main() {
fmt.Println(m)
}


### 修改映射


在映射 `m` 中插入或修改元素:



m[key] = elem

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

import “fmt”

type Vertex struct {
Lat, Long float64
}

var m = map[string]Vertex{
“Bell Labs”: {40.68433, -74.39967},
“Google”: {37.42202, -122.08408},
}

func main() {
fmt.Println(m)
}


### 修改映射


在映射 `m` 中插入或修改元素:



m[key] = elem

[外链图片转存中…(img-9735n9oI-1715809252190)]
[外链图片转存中…(img-W2mEOTev-1715809252190)]
[外链图片转存中…(img-AJDH4WTS-1715809252190)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 25
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值