初始化基本一样,不同点需要注意,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上修改
扫描二维码关注公众号,回复:
3529814 查看本文章
清理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行可以正确运行