请选择 进入手机版 | 继续访问电脑版
设为首页 收藏本站
开启辅助访问 快捷导航
菜单
从零开始 资讯 查看内容

Go常用的数据结构

2020-2-19 19:46 发布者: 干将发硎鞘 评论 0 查看 145
Go常用的数据结构闲着无事,随便写写,初学Go,望各位大神轻喷!Go自带的几个复合数据类型,基本数据类型咱就不说了,大部分语言常见的几种复合数据类型大概有数组、字典、对象等,不同语言叫法不一样,用法也有差异 ...

Go常用的数据结构


闲着无事,随意写写,初学Go,望列位大神轻喷!Go自带的几个复合数据范例,根基数据范例咱就不说了,大部分说话常见的几种复合数据范例大要稀有组、字典、工具等,分歧说话叫法纷歧样,用法也有差别,比如说PHP里面数组实在严酷来说不算数组。

1.数组

Go里面的数组和C类似,是由有序牢固长度特定范例元素组成。画重点,牢固长度和特定范例。在很多弱范例的说话里面,数组很是随意,PHP的数组本质上是一个hash table,和C的数组差别太大,所以写惯了PHP再写Go的话这点需要留意。

根本用法1:
package main
import "fmt"
func main() {
\tvar a [5]int
\ta[1] = 1
\ta[2] = 3
\tvar b [10]string
\tb[0] = "a1"
\tb[1] = "b2"
\tb[2] = "c5"
\tfmt.Printf("%v\\n", a)
\tfmt.Printf("%v\\n", b)
}
---成果---
[0 1 3 0 0]
[a1 b2 c5 ]
复制代码

从语法上看,Go界说数组的范例放在前面,这点写惯C系说话的估量蛋疼。数组也是经过索引下标拜候,假如不初始化赋值的话,默许情况下,int范例的元素是0,string范例是空字符串。

根本用法2

我们也可以不先界说,间接利用字面量初始化数组:
package main
import "fmt"
func main() {
\ta := [...]int{1, 2, 3, 4, 5, 7}
\tfmt.Printf("%v", a)
}
---成果---
[1 2 3 4 5 7]
复制代码

在这类情况下,我们可以省略长度,利用3个点取代,编译器会自动判定。

数组遍历

首要有两种方式:
package main
import "fmt"
func main() {
\ta := [...]int{1, 2, 3, 4, 5, 7}
\tfor i := 0; i < len(a); i++ {
\t\tfmt.Print(a[i])
\t}
\t
\tfor k, v := range a {
\t\tfmt.Print(k, "->", v)
\t}
}
复制代码

假如晓得长度的话可以利用for循环,否则可以利用for range 这类语法。

数组函数

Go内置了一些函数可以操纵数组,假如你利用了IDE的话,可以“点”出来:

Go常用的数据结构_资讯_2020-2-19 19:46发布_从零开始_145

但是,append并不是用来操纵数组的,实在它是用来操纵变长数组的,即slice, 又称切片。

2.Slice(切片)

传统的数组长度牢固,所以现适用处并不多,除非你明白晓得自己想要多长的数组,很多时辰我们需要的是一个可以改变长度巨细的数组,在Go里面这范例被称为切片。

slice实在是从数组而来的,它和数组很是像,区分就在于slice没有牢固长度,很是方便,所以平常一般都是用这个比力多。

根本用法1:
package main
import "fmt"
func main() {
\tvar a []int
\ta = append(a, 2)
\ta = append(a, 1)
\ta = append(a, 4)
\ta = append(a, 5)
\tfmt.Printf("%v", a)
}
复制代码

区分就在于slice在界说的时辰不需要指定长度,也不用3个点,可是这就意味着你不能利用索引下标的方式去赋值了,可以利用append函数去追加元素。

而且在利用slice的也需要留意下标,假如大于slice的长度也会出现 panic: runtime error: index out of range。

根本用法2
package main
import "fmt"
func main() {
\ta := [...]int{1,2,3,4,5,6,7,8}
\ts1 := a[0:]
\ts2 := a[1:5]
\ts3 := a[4:6]
\tfmt.Printf("%v\\n", a)
\tfmt.Printf("%v\\n", s1)
\tfmt.Printf("%v\\n", s2)
\tfmt.Printf("%v\\n", s3)
}
复制代码

slice可以利用[start:end]这类语法从一个数组里面天生,比如a[1:5]意义是天生一个包括数组索引1到5的之间元素的slice。

在Go里面分歧长度可是同一范例的数组是分歧范例的,比如你界说了2个int数组,一个长度为5,一个长度为10,他们实在并不是同一个范例,虽然都是int范例。cannot use a (type [10]int) as type [5]int in argument

所以在大部分时辰我们需要的是一个slice,并不是一个数组。虽然这个2个用法根基上一毛一样。。。

3.Map

在很多说话里面,map被叫作字典,这其中文称号很亲热,字典就是一种key value结构,小时辰大师都用过新华字典,字典的特征就是每一个字都对应一个诠释。可是Go的map是无序的,这点大师需要留意。倘使有童鞋写过PHP,会发现这个数据范例类似PHP里面的关联数组。

在Go里面,它和slice的区分就是slice的索引是数值,map的索引范例就丰富了,根基上常用数据范例都支持,甚至包括结构体。

根本用法

和别的数组范例一样,map也支持先界说后赋值,大概间接利用字面量建立。可是假如利用先界说后赋值这类方式,map需要利用make初始化。
package main
import "fmt"
func main() {
\tvar m1 map[string]string
\tm1 = make(map[string]string)
\tm1["name"] = "Golang"
\tm1["address"] = "BeiJin"
\tm2 := map[string]string{
\t\t"name": "GoLand",
\t\t"addr": "ShangHai",
\t}
\tfmt.Printf("%v\\n", m1)
\tfmt.Printf("%v", m2)
}
---成果---
map[name:Golang address:BeiJin]
map[name:GoLand addr:ShangHai]
复制代码

map可以利用for range 语法遍历,可是需要留意的是每次遍历的顺序是无序的。

若何判定一个key能否存在map里面?在PHP里面我们有一个array_key_exists函数,在Go里面写法略有分歧:
age, ok := m1["age"]
if !ok {
fmt.Println("age 不存在", age)
}
复制代码

实在假如你不判定能否存在间接取也可以,并不会报错,只不外获得到的值是一个对应范例的零值。

4.结构体

Go的结构体也类似C,类似于现在很多面向工具的说话里面的类,常常用来存储一组相关联的数据,Go虽然不是一个完周全向工具的说话,可是利用结构体可以实现类似结果。

根基用法
package main
import "fmt"
type Goods struct {
\tname string
\tprice int
\tpic string
\taddress string
}
func main() {
\tvar goods Goods
\tgoods.name = "商品1"
\tgoods.price = 100
\tgoods.pic = "http://xxxx.jpg"
\tgoods.address = "中国"
\tfmt.Printf("%v\\n", goods)
\tgoods2 := Goods{
\t\tname: "商品2",
\t\tprice: 200,
\t\tpic: "http://xxxx.png",
\t\taddress: "日本",
\t}
\tfmt.Printf("%v", goods2)
}
---成果---
{商品1 100 http://xxxx.jpg 中国}
{商品2 200 http://xxxx.png 日本}
复制代码

先界说后赋值大概字面量赋值都可以,值得一提的是在Go里面假如结构体大概其属性的首字母大写则暗示该结构体大概属性可以被导出,也就是被别的包利用。结构体里面的属性成员的范例也可以是结构体,这就变相实现了类的继续。

既然结构体和类差不多,那类的方式在那里界说呢?这点Go实现的就比力奇妙了!
func (g Goods) getName() string {
\treturn g.name
}
复制代码

我们只需要在函数的前面放一个变量,就酿成了方式。在很多说话里面,函数和方式区分不是很明显,大部分时辰我们都是混着叫,可是在Go里面,方式指的是针对某一范例的函数。比如在上面的例子里面,这个getName函数就是针对Goods结构体的,用面向工具的说法就是一个类方式。所以我们可以利用 goods.getName()的形式挪用这个方式。

上面的代码里阿谁附加的参数p,叫做方式的接收器(receiver),早期的面向工具说话留下的遗产将挪用一个方式称为“向一个工具发送消息”。 在Go说话中,我们并不会像别的说话那样用this大概self作为接收器;我们可以肆意的挑选接收器的名字。由于接收器的名字经常会被利用到,所以连结其在方式间传递时的分歧性和简短性是不错的主张。这里的倡议是可以利用其范例的第一个字母。

在Go里面我们可以为任何范例界说方式,不管是常见的int、string,还是map、struct都没题目,下面的例子里面就是为int范例扩大一个方式:
package main
import "fmt"
type MyInt int
func main() {
\tmyInt := MyInt(10)
\tres := myInt.add(100)
\tfmt.Printf("%d", res)
}
func (m MyInt) add(a int) int {
\treturn int(m) + a
}
---成果---
110
复制代码

我们没法间接利用根基数据范例,可是我们可以起一个体名,纯属文娱!

5.JSON

严酷来说,JSON并不是一种数据范例,可是json是现在最风行的数据交换格式,Go对json的支持也很好,在Go里面首要经过结构体天生json,我们也可以把一个json转换成结构体。
package main
import (
\t"encoding/json"
\t"fmt"
)
type Goods struct {
\tName string
\tPrice int
\tAddress string `json:"address2"`
\tTag string
}
func main() {
\tgoods := Goods{
\t\t"商品1", 100, "中国", "特价",
\t}
\tbytes, err := json.Marshal(goods)
\tif err != nil {
\t\tpanic(err)
\t}
\tfmt.Printf("%s", bytes)
}
---成果---
{"Name":"商品1","Price":100,"address2":"中国","Tag":"特价"}
复制代码

把结构体转换成json可以利用Marshal方式,有一点需要留意: 结构体的属性成员首字母必须大写,可是可以利用注解的Tag标注转换成json以后的key称号。

json字符串转换成结构体步调差不多:
package main
import (
\t"encoding/json"
\t"fmt"
)
type Goods struct {
\tName string
\tPrice int
\tAddress string `json:"address2"`
\tTag string
}
func main() {
\tjsonStr := `{"Name":"商品1","Price":100,"address2":"中国","Tag":"特价"}`
\tgoods := Goods{}
\terr := json.Unmarshal([]byte(jsonStr), &goods)
\tif err != nil {
\t\tpanic(err)
\t}
\tfmt.Printf("%v", goods)
}
---成果---
{商品1 100 特价}
复制代码

这在我们平常写接口大概请求接口的时辰很是好使,简单易用!

好了,明天就先容这么多了,感谢大师检察!


鲜花

握手

雷人

路过

鸡蛋
收藏 分享 邀请

相关阅读

最新评论

一周热门

头条攻略!

日排行榜

相关分类