初始化基本一样,不同点需要注意,make使用,nil变量的访问
array
初始化:
- 57 //修改元素值函数,指针版本和副本版本,指针版会修改原值
- 58 func modify(arr [3]int, i int, v int) {
- 59 //func modify(arr *[3]int, i int, v int) {
- 60 arr[i] = v
- 61 }
- 62
- 63 func main() {
- 64 var v [2]int //默认初始化为0
- 65 v1 := [2]int{} //默认初始化为0
- 66 v2 := [...]int{} //根据初始化列表决定元素个数,元素个数为0
- 67 v3 := [3]int{2: 99} //指定索引初始化
- 68
- 69 fmt.Println(v, v1, v2, v3)
- 70 }
slice
初始化:
- 71 //切片函数参数版本
- 72 func modify(arr []int, i int, v int) {
- 73 arr[i] = v
- 74 }
- 75
- 76 func main() {
- 77 //和数组区别在于是否指定元素个数,和数组一样都是有长度的,所有随机访问时小心越界
- 78 var v []int //v == nil,nil值切片没有底层数组
- 79 vv := []int(nil) //vv == nil,nil值切片没有底层数组
- 80
- 81 v0 := []int{} //v != nil,nil切片和0长度切片行为一致,函数会等同对待
- 82 v1 := []int{1, 2}
- 83
- 84 var arr [3]int
- 85 v2 := arr[:]
- 86 v3 := arr[2:]
- 87
- 88 v3 = v1
- 89 modify(v3, 0, 111)
- 90 v2 = nil
- 91
- 92 v4 := make([]int, 3, 6) //若不指定cap,则和len一致
- 93
- 94 //v5 := make([]int, 4)
- 95 //v5 = v4[4:] //panic:slice bounds out of range,v4超过了len()
- 96 v4 = push(v4, 123)
- 97 v4 = push(v4, 123)
- 98 v4 = push(v4, 123)
- 99 v4 = push(v4, 123)
- 100
- 101 fmt.Println(v == nil, vv == nil, v0 == nil, v1, v2 == nil, v3, cap(v4), len(v4), v4)
- 102
- 103 }
数组可以用==进行比较,切片编译错误
append简单实现:
- 45 func push(s []int, v int) []int {
- 46 var tmp_s []int
- 47 if len(s) < cap(s) {
- 48 tmp_s = s[:(len(s) + 1)]
- 49 } else {
- 50 tmp_s = make([]int, len(s)+1, 2*len(s))
- 51 copy(tmp_s, s)
- 52 }
- 53
- 54 tmp_s[len(s)] = v
- 55
- 56 return tmp_s
- 57 }
copy函数,按照src,dst最小长度进行底层数组数据拷贝
appen使用:
- 105 v5 := make([]int, 2, 6)
- 106 v5 = append(v5, 1, 2)
- 107 v5 = append(v5, v4...)
append变长简单实现:
- 76 func push_s(s []int, v ...int) []int {
- 77 var tmp = make([]int, len(s)+len(v))
- 78 copy(tmp, s)
- 79 copy(tmp[len(s):], v)
- 80
- 81 return tmp
- 82 }
slice内存技巧:
不用分配新空间,在原slice上修改
清理0数据
- 84 func RemoveInvalid2(s []int) []int {
- 85 i := 0
- 86 for _, v := range s {
- 87 if v != 0 {
- 88 s[i] = v
- 89 i++
- 90 }
- 91 }
- 92
- 93 return s[:i]
- 94 }
- 95
- 96 func RemoveInvalid(s []int) []int {
- 97 s_tmp := s[:0]
- 98 for _, v := range s {
- 99 if v != 0 {
- 100 s_tmp = append(s_tmp, v)
- 101 }
- 102 }
- 103
- 104 return s_tmp
- 105 }
- 107 func RemoveIndex(s []int, i int) []int {
- 108 if i >= len(s) {
- 109 return s
- 110 }
- 111 copy(s[i:], s[i+1:])
- 112 return s[:len(s)-1]
- 113 }
- 114
- 115 func Reverse(s []int) []int {
- 116 if len(s) < 2 {
- 117 return s
- 118 }
- 119 for i := range s {
- 120 if i >= (len(s) - i - 1) {
- 121 return s
- 122 }
- 123 s[i], s[len(s)-i-1] = s[len(s)-i-1], s[i]
- 124 }
- 125 return s
- 126 }
我们也看到了slice作为函数参数的使用,同样map也是会作为引用来使用的,使用时要注意slice和map内部变化,防止得不到想要的结果,所以我一般会在函数返回后进行赋值
map
- 128 func insert(m map[int]string, i int, s string) map[int]string {
- 129 m[i] = s
- 130 return m
- 131 }
- 132
- 133 func main() {
- 134 var m map[int]string
- 135 m1 := map[int]string{2: "ss", 5: "aa"}
- 136 delete(m1, 5)
- 137
- 138 m2 := make(map[int]string)
- 139 m3 := map[int]string{}
- 140 m3 = insert(m3, 2, "aaaaaaa")
- 141
- 142 m4 := make(map[int]map[string]bool)
- 143 fmt.Println(m == nil, m1, m2, m3, m4)
- 144 }
注意:key必须是可比较的类型,如字符串,数组(可比较的字段),结构体(可比较的字段)
slice不能比较,但可以转换成字符串再存储为key
struct
- 149 type Point struct {
- 150 x, y float64
- 151 }
- 152
-
- 158
- 159 type line struct {
- 160 pt []Point
- 161 }
- 163 func main() {
- 164 /*
- 165 l := []struct {
- 166 pt []Point
- 167 cnt int
- 168 }{{
- 169 pt: []Point{{
- 170 x: 1,
- 171 y: 2,
- 172 }, {
- 173 x: 3,
- 174 y: 4,
- 175 }},
- 176 cnt: 2,
- 177 }}
- 178 */
- 179
- 180 var pt Point
- 181 pt.x = 1
- 182 pt.y = 2
- 183
- 184 pt1 := Point{1, 2} //这种初始化方式不推荐,建议用下方
- 185 pt2 := Point{x: 1, y: 2}
- 186
- 187 l := []line{}
- 188
- 189 var l1 line
- 190 //l1 := line{}
- 191
- 192 l = append(l, l1)
- 193 l[0].pt = append(l[0].pt, Point{11, 22})
- 194 fmt.Println(pt, pt1, pt2, l, l1)
- 195 }
结构方法使用
- 153 //func (p *Point) Distance(target *Point) float64 {
- 154 func (p Point) Distance(target *Point) float64 {
- 154 p.x = 0.1
- 155 target.x = 0.2
- 156 return 0.0
- 157 }
-
- 197 pt.Distance(&pt1)
- 198 fmt.Println(pt, pt1)
改变函数调用方类型,试试结果的不同
go会根据调用方类型隐式转换,所以197行可以正确运行