You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
golang-tutorial/docs/golang_tutorial_04.md

350 lines
9.0 KiB

4 - 类型
========================
这是本Golang系列教程的第四篇。你可以阅读 Golang 系列教程 第 3 部分:[变量](/docs/golang_tutoria_03.md) 。来学习有关变量的知识。
下面是 Go 支持的基本类型
* bool
* Numeric Types
* int8, int16, int32, int64, int
* uint8, uint16, uint32, uint64, uint
* float32, float64
* complex64, complex128
* byte
* rune
* string
## bool
bool 类型表示一个布尔值,值为 true 或者 false。
```golang
package main
import "fmt"
func main() {
a := true
b := false
fmt.Println("a:", a, "b:", b)
c := a && b
fmt.Println("c:", c)
d := a || b
fmt.Println("d:", d)
}
```
在上面的程序中a 赋值为 trueb 赋值为 false。
c 赋值为 a && b。仅当 a 和 b 都为 true 时,操作符 && 才返回 true。因此在这里 c 为 false。
当 a 或者 b 为 true 时,操作符 || 返回 true。在这里由于 a 为 true因此 d 也为 true。
我们将会得到如下输出:
```golang
a: true b: false
c: false
d: true
```
## 有符号整型
int8表示 8 位有符号整型
大小8 位
范围:`-128127`
int16表示 16 位有符号整型
大小16 位
范围:`-3276832767`
int32表示 32 位有符号整型
大小32 位
范围:`-21474836482147483647`
int64表示 64 位有符号整型
大小64 位
范围:`-92233720368547758089223372036854775807`
int根据不同的底层平台Underlying Platform表示 32 或 64 位整型。除非对整型的大小有特定的需求,否则你通常应该使用 int 表示整型。
大小:在 32 位系统下是 32 位,而在 64 位系统下是 64 位。
范围:在 32 位系统下是 `-21474836482147483647`,而在 64 位系统是 `-92233720368547758089223372036854775807`
```golang
package main
import "fmt"
func main() {
var a int = 89
b := 95 // 简短
fmt.Println("value of a is", a, "and b is", b)
}
```
如下输出:
```golang
value of a is 89 and b is 95
```
在上述程序中a 是 int 类型,而 b 的类型通过赋值95推断得出。上面我们提到int 类型的大小在 32 位系统下是 32 位,而在 64 位系统下是 64 位。接下来我们会证实这种说法。
在 Printf 方法中,使用 `%T` 格式说明符Format Specifier可以打印出变量的**类型**。Go 的 unsafe 包提供了一个 Sizeof 函数该函数接收变量并返回它的字节大小。unsafe 包应该小心使用,因为使用 unsafe 包可能会带来可移植性问题。不过出于本教程的目的,我们是可以使用的。
下面程序会输出变量 a 和 b 的类型和大小。格式说明符 %T 用于打印类型,而 %d 用于打印字节大小。
```golang
package main
import (
"fmt"
"unsafe"
)
func main() {
var a int = 89
b := 95
fmt.Println("value of a is", a, "and b is", b)
fmt.Printf("type of a is %T, size of a is %d", a, unsafe.Sizeof(a)) //type and size of a
fmt.Printf("\ntype of b is %T, size of b is %d", b, unsafe.Sizeof(b)) //type and size of b
}
```
以上程序会输出:
```golang
value of a is 89 and b is 95
type of a is int, size of a is 4
type of b is int, size of b is 4
```
从上面的输出,我们可以推断出 a 和 b 为 int 类型,且大小都是 32 位4 字节)。如果你在 64 位系统上运行上面的代码,会有不同的输出。在 64 位系统下a 和 b 会占用 64 位8 字节)的大小。
以下为windows 64位系统运行结果非翻译案例
```golang
value of a is 89 and b is 95
type of a is int, size of a is 8
type of b is int, size of b is 8
```
## 无符号整型
uint8表示 8 位无符号整型
大小8 位
范围0255
uint16表示 16 位无符号整型
大小16 位
范围065535
uint32表示 32 位无符号整型
大小32 位
范围04294967295
uint64表示 64 位无符号整型
大小64 位
范围018446744073709551615
uint根据不同的底层平台表示 32 或 64 位无符号整型。
大小:在 32 位系统下是 32 位,而在 64 位系统下是 64 位。
范围:在 32 位系统下是 04294967295而在 64 位系统是 018446744073709551615。
## 浮点型
float3232 位浮点数
float6464 位浮点数
下面一个简单程序演示了整型和浮点型的运用。
```golang
package main
import (
"fmt"
)
func main() {
a, b := 5.67, 8.97
fmt.Printf("type of a %T b %T\n", a, b)
sum := a + b
diff := a - b
fmt.Println("sum", sum, "diff", diff)
no1, no2 := 56, 89
fmt.Println("sum", no1+no2, "diff", no1-no2)
}
```
a 和 b 的类型根据赋值推断得出。在这里a 和 b 的类型为 float64float64 是浮点数的默认类型)。我们把 a 和 b 的和赋值给变量 sum把 b 和 a 的差赋值给 diff接下来打印 sum 和 diff。no1 和 no2 也进行了相同的计算。上述程序将会输出:
```golang
type of a float64 b float64
sum 14.64 diff -3.3000000000000007
sum 145 diff -33
```
## 复数类型
complex64实部和虚部都是 float32 类型的的复数。
complex128实部和虚部都是 float64 类型的的复数。
内建函数 complex 用于创建一个包含实部和虚部的复数。complex 函数的定义如下:
```golang
func complex(r, i FloatType) ComplexType
```
该函数的参数分别是实部和虚部,并返回一个复数类型。实部和虚部应该是相同类型,也就是 float32 或 float64。如果实部和虚部都是 float32 类型,则函数会返回一个 complex64 类型的复数。如果实部和虚部都是 float64 类型,则函数会返回一个 complex128 类型的复数。
还可以使用简短语法来创建复数:
```golang
c := 6 + 7i
```
下面我们编写一个简单的程序来理解复数:
```golang
package main
import (
"fmt"
)
func main() {
c1 := complex(5,7)
c2 := 8 + 27i
cadd := c1 + c2
fmt.Println("sum:",cadd)
cmul := c1 * c2
fmt.Println("mul :",cmul)
}
```
在上面的程序里c1 和 c2 是两个复数。c1的实部为 5虚部为 7。c2 的实部为8虚部为 27。c1 和 c2 的和赋值给 cadd ,而 c1 和 c2 的乘积赋值给 cmul。该程序将输出
```golang
sum: (13+34i)
mul : (-149+191i)
```
## 其他数字类型
byte 是 uint8 的别名。
rune 是 int32 的别名。
在学习字符串的时候,我们会详细讨论 byte 和 rune。
## string 类型
在 Golang 中,字符串是字节的集合。如果你现在还不理解这个定义,也没有关系。我们可以暂且认为一个字符串就是由很多字符组成的。我们后面会在一个教程中深入学习字符串。 下面编写一个使用字符串的程序。
```golang
package main
import (
"fmt"
)
func main() {
first := "Wan"
last := "ShaoBo"
name := first +" "+ last
fmt.Println("My name is",name)
}
```
上面程序中first 赋值为字符串 "Naveen"last 赋值为字符串 "Ramanathan"。+ 操作符可以用于拼接字符串。我们拼接了 first、空格和 last并将其赋值给 name。
上述程序将打印输出:
```golang
My name is Wan ShaoBo
```
还有许多应用于字符串上面的操作,我们将会在一个单独的教程里看见它们。
## 类型转换
Go 有着非常严格的强类型特征。Go 没有自动类型提升或类型转换。我们通过一个例子说明这意味着什么。
```golang
package main
import (
"fmt"
)
func main() {
i := 55 //int
j := 67.8 //float64
sum := i + j //不允许 int + float64
fmt.Println(sum)
}
```
上面的代码在 C 语言中是完全合法的,然而在 Go 中却是行不通的。i 的类型是 int ,而 j 的类型是 float64 我们正试图把两个不同类型的数相加Go 不允许这样的操作。如果运行程序,你会得到
```golang
# command-line-arguments
demo04\demo04-07.go:10:14: invalid operation: i + j (mismatched types int and float64)
```
要修复这个错误i 和 j 应该是相同的类型。在这里,我们把 j 转换为 int 类型。把 v 转换为 T 类型的语法是 T(v)。
```golang
package main
import (
"fmt"
)
func main() {
i := 55 //int
j := 67.8 //float64
sum := i + int(j) //j is converted to int
fmt.Println(sum)
}
```
现在,当你运行上面的程序时,会看见输出
```golang
122
```
赋值的情况也是如此。把一个变量赋值给另一个不同类型的变量,需要显式的类型转换。下面程序说明了这一点。
```golang
package main
import (
"fmt"
)
func main() {
i := 10
var j float64 = float64(i) // 若没有显式转换,该语句会报错
fmt.Println("j", j)
}
```
在第 9 行i 转换为 float64 类型,接下来赋值给 j。如果不进行类型转换当你试图把 i 赋值给 j 时,编译器会抛出错误。