闲着无事,随便写写,初学Go,望各位大神轻喷!Go自带的几个复合数据类型,基本数据类型咱就不说了,大部分语言常见的几种复合数据类型大概有数组、字典、对象等,不一样语言叫法不同,用法也有差别,好比说PHP里面数组其实严格来讲不算数组。json
Go里面的数组和C相似,是由有序的固定长度的特定类型元素组成。画重点,固定长度和特定类型。在不少弱类型的语言里面,数组很是随意,PHP的数组本质上是一个hash table,和C的数组差别太大,因此写惯了PHP再写Go的话这点须要注意。数组
package main
import "fmt"
func main() {
var a [5]int
a[1] = 1
a[2] = 3
var b [10]string
b[0] = "a1"
b[1] = "b2"
b[2] = "c5"
fmt.Printf("%v\n", a)
fmt.Printf("%v\n", b)
}
---结果---
[0 1 3 0 0]
[a1 b2 c5 ]
复制代码
从语法上看,Go定义数组的类型放在后面,这点写惯C系语言的估计蛋疼。数组也是经过索引下标访问,若是不初始化赋值的话,默认状况下,int类型的元素是0,string类型是空字符串。bash
咱们也能够不先定义,直接使用字面量初始化数组:app
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3, 4, 5, 7}
fmt.Printf("%v", a)
}
---结果---
[1 2 3 4 5 7]
复制代码
在这种状况下,咱们能够省略长度,使用3个点代替,编译器会自动判断。函数
主要有两种方式:ui
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3, 4, 5, 7}
for i := 0; i < len(a); i++ {
fmt.Print(a[i])
}
for k, v := range a {
fmt.Print(k, "->", v)
}
}
复制代码
若是知道长度的话可使用for循环,不然可使用for range 这种语法。this
Go内置了一些函数能够操做数组,若是你使用了IDE的话,能够“点”出来:spa
然而,append并非用来操做数组的,其实它是用来操做变长数组的,即slice, 又称切片。3d
传统的数组长度固定,因此实际用途并很少,除非你明确知道本身想要多长的数组,不少时候咱们须要的是一个能够改变长度大小的数组,在Go里面这类型被称为切片。code
slice实际上是从数组而来的,它和数组很是像,区别就在于slice没有固定长度,很是方便,因此平时通常都是用这个比较多。
package main
import "fmt"
func main() {
var a []int
a = append(a, 2)
a = append(a, 1)
a = append(a, 4)
a = append(a, 5)
fmt.Printf("%v", a)
}
复制代码
区别就在于slice在定义的时候不须要指定长度,也不用3个点,可是这就意味着你不能使用索引下标的方法去赋值了,可使用append函数去追加元素。
并且在使用slice的也须要注意下标,若是大于slice的长度也会出现 panic: runtime error: index out of range
。
package main
import "fmt"
func main() {
a := [...]int{1,2,3,4,5,6,7,8}
s1 := a[0:]
s2 := a[1:5]
s3 := a[4:6]
fmt.Printf("%v\n", a)
fmt.Printf("%v\n", s1)
fmt.Printf("%v\n", s2)
fmt.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个用法基本上一毛同样。。。
在不少语言里面,map被叫做字典,这个中文名称很亲切,字典就是一种key value结构,小时候你们都用过新华字典,字典的特征就是每个字都对应一个解释。可是Go的map是无序的,这点你们须要注意。若是有童鞋写过PHP,会发现这个数据类型相似PHP里面的关联数组。
在Go里面,它和slice的区别就是slice的索引是数值,map的索引类型就丰富了,基本上经常使用数据类型都支持,甚至包括结构体。
和其它数组类型同样,map也支持先定义后赋值,或者直接使用字面量建立。可是若是使用先定义后赋值这种方式,map须要使用make初始化。
package main
import "fmt"
func main() {
var m1 map[string]string
m1 = make(map[string]string)
m1["name"] = "Golang"
m1["address"] = "BeiJin"
m2 := map[string]string{
"name": "GoLand",
"addr": "ShangHai",
}
fmt.Printf("%v\n", m1)
fmt.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)
}
复制代码
其实若是你不判断是否存在直接取也能够,并不会报错,只不过获取到的值是一个对应类型的零值。
Go的结构体也相似C,相似于如今不少面向对象的语言里面的类,每每用来存储一组相关联的数据,Go虽然不是一个彻底面向对象的语言,可是使用结构体能够实现相似效果。
package main
import "fmt"
type Goods struct {
name string
price int
pic string
address string
}
func main() {
var goods Goods
goods.name = "商品1"
goods.price = 100
goods.pic = "http://xxxx.jpg"
goods.address = "中国"
fmt.Printf("%v\n", goods)
goods2 := Goods{
name: "商品2",
price: 200,
pic: "http://xxxx.png",
address: "日本",
}
fmt.Printf("%v", goods2)
}
---结果---
{商品1 100 http://xxxx.jpg 中国}
{商品2 200 http://xxxx.png 日本}
复制代码
先定义后赋值或者字面量赋值均可以,值得一提的是在Go里面若是结构体或者其属性的首字母大写则表示该结构体或者属性能够被导出,也就是被其它包使用。结构体里面的属性成员的类型也能够是结构体,这就变相实现了类的继承。
既然结构体和类差很少,那类的方法在哪里定义呢?这点Go实现的就比较巧妙了!
func (g Goods) getName() string {
return 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() {
myInt := MyInt(10)
res := myInt.add(100)
fmt.Printf("%d", res)
}
func (m MyInt) add(a int) int {
return int(m) + a
}
---结果---
110
复制代码
咱们没法直接使用基本数据类型,可是咱们能够起一个别名,纯属娱乐!
严格来讲,JSON并非一种数据类型,可是json是如今最流行的数据交换格式,Go对json的支持也很好,在Go里面主要经过结构体生成json,咱们也能够把一个json转换成结构体。
package main
import (
"encoding/json"
"fmt"
)
type Goods struct {
Name string
Price int
Address string `json:"address2"`
Tag string
}
func main() {
goods := Goods{
"商品1", 100, "中国", "特价",
}
bytes, err := json.Marshal(goods)
if err != nil {
panic(err)
}
fmt.Printf("%s", bytes)
}
---结果---
{"Name":"商品1","Price":100,"address2":"中国","Tag":"特价"}
复制代码
把结构体转换成json可使用Marshal方法,有一点须要注意: 结构体的属性成员首字母必须大写,可是可使用注解的Tag标注转换成json以后的key名称。
json字符串转换成结构体步骤差很少:
package main
import (
"encoding/json"
"fmt"
)
type Goods struct {
Name string
Price int
Address string `json:"address2"`
Tag string
}
func main() {
jsonStr := `{"Name":"商品1","Price":100,"address2":"中国","Tag":"特价"}`
goods := Goods{}
err := json.Unmarshal([]byte(jsonStr), &goods)
if err != nil {
panic(err)
}
fmt.Printf("%v", goods)
}
---结果---
{商品1 100 特价}
复制代码
这在咱们平时写接口或者请求接口的时候很是好使,简单易用!
好了,今天就介绍这么多了,谢谢你们查看!