布尔

布尔类型关键字是 bool,布尔类型只有2个值分别为 true 或者 false。

  1. func main() {
  2. a:= true
  3. b:= false
  4. fmt.Println(a)
  5. fmt.Println(b)
  6. c:=a&&b
  7. fmt.Println(c)
  8. d:=a||b
  9. fmt.Println(d)
  10. }

在上面的程序中,a 赋值为 true,b 赋值为 false。c 赋值为 a && b。仅当 a 和 b 都为 true 时,操作符 && 才返回 true。因此,在这里 c 为 false。当 a 或者 b 为 true 时,操作符 || 返回 true。在这里,由于 a 为 true,因此 d 也为 true。我们将得到程序的输出如下。

  1. true
  2. false
  3. false
  4. true

数字类型和bool类型不能相互转换,这个可能跟一些语言不太一,需要特别注意

  1. var a bool
  2. a = 1

上面的语句执行会出现如下错误提示

  1. cannot use 1 (type int) as type bool in assignment

数字

有符号整型

类型 描述 大小 范围
int8 表示 8 位有符号整型 8 位 -128~127
int16 表示 16 位有符号整型 16 位 -32768~32767
int32 表示 32 位有符号整型 32 位 -2147483648~2147483647
int64 表示 64 位有符号整型 64 位 -9223372036854775808~9223372036854775807
  1. package main
  2. import "fmt"
  3. func main() {
  4. var a int = 89
  5. b := 95
  6. fmt.Println("value of a is", a, "and b is", b)
  7. }

上面程序会输出

  1. value of a is 89 and b is 95

在 Printf 方法中,使用 %T 格式说明符(Format Specifier),可以打印出变量的类型。Go 的 unsafe 包提供了一个 Sizeof 函数,该函数接收变量并返回它的字节大小。unsafe 包应该小心使用,因为使用 unsafe 包可能会带来可移植性问题。
下面程序会输出变量 a 和 b 的类型和大小。格式说明符 %T 用于打印类型,而 %d 用于打印字节大小。

  1. package main
  2. import (
  3. "fmt"
  4. "unsafe"
  5. )
  6. func main() {
  7. var a int = 89
  8. b := 95
  9. fmt.Println("value of a is", a, "and b is", b)
  10. fmt.Printf("type of a is %T, size of a is %d", a, unsafe.Sizeof(a)) // a 的类型和大小
  11. fmt.Printf("\ntype of b is %T, size of b is %d", b, unsafe.Sizeof(b)) // b 的类型和大小
  12. }

以上程序会输出:

  1. value of a is 89 and b is 95
  2. type of a is int, size of a is 4
  3. type of b is int, size of b is 4

从上面的输出,我们可以推断出 a 和 b 为 int 类型,且大小都是 32 位(4 字节)。如果你在 64 位系统上运行上面的代码,会有不同的输出。在 64 位系统下,a 和 b 会占用 64 位(8 字节)的大小。

无符号整型

类型 描述 大小 范围
uint8 表示 8 位无符号整型 8 位 0~255
uint16 表示 16 位无符号整型 16 位 0~65535
uint32 32 位无符号整型 32 0~4294967295
uint64 64 位无符号整型 64 位 0~18446744073709551615
uint 根据不同的底层平台,表示 32 或 64 位无符号整型 在 32 位系统下是 32 位,而在 64 位系统下是 64 位 在 32 位系统下是 0~4294967295,而在 64 位系统是 0~18446744073709551615。

浮点型

float32:32 位浮点数
float64:64 位浮点数
eg:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. a, b := 5.67, 8.97
  7. fmt.Printf("type of a %T b %T\n", a, b)
  8. sum := a + b
  9. diff := a - b
  10. fmt.Println("sum", sum, "diff", diff)
  11. no1, no2 := 56, 89
  12. fmt.Println("sum", no1+no2, "diff", no1-no2)
  13. }

a 和 b 的类型根据赋值推断得出。在这里,a 和 b 的类型为 float64(float64 是浮点数的默认类型)。我们把 a 和 b 的和赋值给变量 sum,把 b 和 a 的差赋值给 diff,接下来打印 sum 和 diff。no1 和 no2 也进行了相同的计算。上述程序将会输出:

  1. type of a float64 b float64
  2. sum 14.64 diff -3.3000000000000007
  3. sum 145 diff -33

注意:浮点数字面量被自动类型推断为 float64类型。

复数类型

complex64:实部和虚部都是 float32 类型的的复数。
complex128:实部和虚部都是 float64 类型的的复数。
内建函数 complex 用于创建一个包含实部和虚部的复数。complex 函数的定义如下:

  1. func complex(r, i FloatType) ComplexType

该函数的参数分别是实部和虚部,并返回一个复数类型。实部和虚部应该是相同类型,也就是 float32 或 float64。如果实部和虚部都是 float32 类型,则函数会返回一个 complex64 类型的复数。如果实部和虚部都是 float64 类型,则函数会返回一个 complex128 类型的复数。

还可以使用简短语法来创建复数:

  1. c := 6 + 7i

下面我们编写一个简单的程序来理解复数。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. c1 := complex(5, 7)
  7. c2 := 8 + 27i
  8. cadd := c1 + c2
  9. fmt.Println("sum:", cadd)
  10. cmul := c1 * c2
  11. fmt.Println("product:", cmul)
  12. }

在上面的程序里,c1 和 c2 是两个复数。c1的实部为 5,虚部为 7。c2 的实部为8,虚部为 27。c1 和 c2 的和赋值给 cadd ,而 c1 和 c2 的乘积赋值给 cmul。该程序将输出:

  1. sum: (13+34i)
  2. product: (-149+191i)

其他数字

byte 是 uint8 的别名。
rune 是 int32 的别名。

字符串

在 Golang 中,字符串是字节的集合。
eg:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. first := "Naveen"
  7. last := "Ramanathan"
  8. name := first +" "+ last
  9. fmt.Println("My name is",name)
  10. }

上面程序中,first 赋值为字符串 “Naveen”,last 赋值为字符串 “Ramanathan”。+ 操作符可以用于拼接字符串。我们拼接了 first、空格和 last,并将其赋值给 name。上述程序将打印输出 My name is Naveen Ramanathan

类型转换

Go 有着非常严格的强类型特征。Go 没有自动类型提升或类型转换。我们通过一个例子说明这意味着什么。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. i := 55 //int
  7. j := 67.8 //float64
  8. sum := i + j //不允许 int + float64
  9. fmt.Println(sum)
  10. }

上面的代码在 C 语言中是完全合法的,然而在 Go 中,却是行不通的。i 的类型是 int ,而 j 的类型是 float64 ,我们正试图把两个不同类型的数相加,Go 不允许这样的操作。如果运行程序,你会得到 main.go:10: invalid operation: i + j (mismatched types int and float64)

要修复这个错误,i 和 j 应该是相同的类型。在这里,我们把 j 转换为 int 类型。把 v 转换为 T 类型的语法是 T(v)。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. i := 55 //int
  7. j := 67.8 //float64
  8. sum := i + int(j) //j is converted to int
  9. fmt.Println(sum)
  10. }

现在,当你运行上面的程序时,会看见输出 122
赋值的情况也是如此。把一个变量赋值给另一个不同类型的变量,需要显式的类型转换。下面程序说明了这一点。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. i := 10
  7. var j float64 = float64(i) // 若没有显式转换,该语句会报错
  8. fmt.Println("j", j)
  9. }

在第 9 行,i 转换为 float64 类型,接下来赋值给 j。如果不进行类型转换,当你试图把 i 赋值给 j 时,编译器会抛出错误。

零值zero Value

零值并非是空值,而是一种“变量未填充前”的默认值

数据类型 默认值
整型 0
浮点型 0
字符串型 “”
布尔型 false
  1. var i int
  2. var a float32
  3. var b float64
  4. var isMarried bool
  5. var name string
  6. fmt.Printf("i=%v,a=%v,b=%v,isMarried=%v,name=%v",i,a,b,isMarried,name)

引用和值类型

引用类型的修改可以影响到任何引用到它的变量。
基本类型因为是拷贝的值,并且在对他进行操作的时候,生成的也是新创建的值

类型 范围
引用类型 切片,字典,通道,函数
值类型 数组,基本数据类型,结构体

全局和局部变量

golang中允许全局变量与局部变量名称可以相同,:= 短变量声明声明的是局部变量DB, var DB *gorm.DB 在函数外部声明的是全局变量,在下面例子中 局部的DB会屏蔽全部的DB, 局部DB的赋值不代表全局的DB被赋值。

  1. var DB *gorm.DB
  2. func InitGorm() error{
  3. dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
  4. DB, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  5. return err
  6. }

正确的写法

  1. var DB *gorm.DB
  2. func InitGorm() error{
  3. var err error
  4. dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
  5. DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
  6. return err
  7. }