go数据结构整理

初始化基本一样,不同点需要注意,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行可以正确运行

猜你喜欢

转载自blog.csdn.net/nawenqiang/article/details/82287582
今日推荐