Go语言圣经(二)数据类型

Posted by YaPi on April 15, 2018

类型分类

  • 基础类型 (数字、字符串、布尔类型)
  • 复合类型 (数组、结构体)
  • 引用类型 (指针、切片、字典、函数、通道)
  • 接口类型

数字类型

无符号整形:int8、int16、int32、int64 有符号整形:uint8、uint16、uint32、uint64

unicode字符rune类型是和int32等价的整形。byte也是uint8类型的等价类型

int类型所占大小在不同的机子上不同,甚至在相同的机子上不同的编译器内也不同

其中有符号整数采用2的补码形式表示,也就是最高bit位用作表示符号位,一个n-bit的有符号数的值域是从−2到2−1。无符号整数的所有bit位都用于表示非负数,值域是0到2−1。例如,int8类型整数的值域是从-128到127,而uint8类型整数的值域是从0到255

fmt.Printf("x = %d e^x = %8.3f\n",x,math.Exp(float64(x)))

打印精度是小数点后三个小数精度和8个字符宽度

字符串

一个字符串是一个不可改变的字节序列。字符串可以包含任意的数据,包括byte值0。文本字符串通过被解释为UTF-8编码的Unicode码点(rune)序列。

复合类型

  • 数组
  • 结构
  • slice
  • map

数组和结构有固定内存大小,slice和map则是动态的数据结构,根据需要动态增长。

数组的长度是数组类型的一个组成部分,因此[3]int和[4]int是两种不同的数组类型

如果一个数组的元素类型是可以相互比较的,那么数组类型也是可以相互比较的,这时候我们可以直接通过==比较运算符来比较两个数组,只有当两个数组的所有元素都是相等的时候数组才是相等的

当调用一个函数的时候,函数的每个调用参数将会被赋值给函数内部的参数变量,所以函数参数变量接收的是一个复制的副本,并不是原始调用的变量。因为函数参数传递的机制导致传递大的数组类型将是低效的,并且对数组参数的任何的修改都是发生在复制的数组上,并不能直接修改调用时原始的数组变量。在这个方面,Go语言对待数组的方式和其它很多编程语言不同,其它编程语言可能会隐式地将数组作为引用或指针对象传入被调用的函数。当然,我们可以显式地传入一个数组指针,那样的话函数通过指针对数组的任何修改都可以直接反馈到调用者

slice

slice之间不能比较,因此我们不能使用==操作符来判断两个slice是否含有全部相等元素。不过标准库提供了高度优化的bytes.Equal函数来判断两个字节型slice是否相等([]byte),但是对于其他类型的slice,我们必须自己展开每个元素进行比较

slice唯一合法的比较操作是和nil比较

一个零值的slice等于nil。一个nil值的slice并没有底层数组。一个nil值的slice的长度和容量都是0,但是也有非nil值的slice的长度和容量也是0的,例如[]int{}或make([]int,3)[3:]。与任意类型的nil值一样,我们可以用[]int(nil)类型转换表达式来生成一个对应类型slice的nil值

内置的make函数创建一个指定元素类型、长度和容量的slice。容量部分可以省略,在这种情况下,容量将等于长度

make([]T, len) make([]T, len, cap) // same as make([]T, cap)[:len]

Map

  • map遍历的顺序是不定的
  • map的零值也是nil
  • 访问map中不存在的元素会返回对应value的零值
  • if apge, ok := ages[“bob”];!ok {}

结构体

  • 结构体可以组合
  • 组合过后的结构体可以直接使用内聚结构体的属性和方法

package main

import (
	"fmt"
)
type People struct{}

func (p *People) ShowA() {
	fmt.Println("showA")
	p.ShowB()
}
func (p *People) ShowB() {
	fmt.Println("showB")
}

type Teacher struct {
	People
}

func (t *Teacher) ShowB() {
	fmt.Println("teacher showB")
}

func main() {
	t := Teacher{}
	t.ShowA()
}

output//

showA
showB

Go中没有继承,上面这种写法叫组合。
func calc(index string, a, b int) int {
    ret := a + b
    fmt.Println(index, a, b, ret)
    return ret
}

func main() {
    a := 1
    b := 2
    defer calc("1", a, calc("10", a, b))
    a = 0
    defer calc("2", a, calc("20", a, b))
    b = 1
}
output//
10 1 2 3
20 0 2 2
2 0 2 2
1 1 3 4