Go 的基本类型有三类:
booltruefalse&&||!stringrunelen()intint8int16int32int64uintuint8uint16uint32uint64uintptrbyterunefloat32float64complex64complex128
byteuint8runeint32𪸿U+2AE3F175679
// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is // used, by convention, to distinguish byte values from 8-bit unsigned // integer values. type byte = uint8 // Go 1.9 开始用户也可以声明自定义的类型别名(type alias) // rune is an alias for int32 and is equivalent to int32 in all ways. It is // used, by convention, to distinguish character values from integer values. type rune = int32
"hello"'𪸿'
2. 变量
var
package main
import "fmt"
// 包级别声明的变量会在 main 入口函数执行前完成初始化
var a int = 10
func main() {
fmt.Printf("%T %v\n", a, a)
// 局部变量将在声明语句被执行到的时候完成初始化
var b int = 20
fmt.Printf("%T %v\n", b, b)
// 可以在一个声明语句中同时声明一组变量:变量类型相同时,保留最后的类型即可
var c, d bool = true, false
fmt.Printf("%T %v\n", c, c)
fmt.Printf("%T %v\n", d, d)
// 可以在一个声明语句中同时声明一组变量:变量类型不同时,不能分别写类型,由 Go 自动进行类型推导
var e, f = "hello", 3.14
fmt.Printf("%T %v\n", e, e)
fmt.Printf("%T %v\n", f, f)
}
/* Output:
int 10
int 20
bool true
bool false
string hello
float32 3.14
*/
分组
var ( b bool = true s string = "hello" i int = 10 f float64 = 3.14 )
一组变量也可以通过调用一个函数,由函数返回的多个返回值初始化:
var f, err = os.Open(name) // os.Open returns a file and an error 表达式在运行时(runtime)被计算
2.1 零值
零值(zero value)
false""0
package main
import "fmt"
func main() {
var b bool
var s string
var i int
var f float64
fmt.Printf("%v %q %v %v\n", b, s, i, f)
}
/* Output:
false "" 0 0
*/
其它零值:
nil
零值初始化机制可以确保每个声明的变量总是有一个良好定义的值,因此在 Go 语言中不存在未初始化的变量。这个特性可以简化很多代码,而且可以在没有增加额外工作的前提下确保边界条件下的合理行为
2.2 类型推导
在声明一个变量而不指定其类型时,变量的类型由右值推导得出
package main
import "fmt"
func main() {
var b, s, i, f = false, "hello", 10, 3.14
fmt.Printf("%T %v\n", b, b)
fmt.Printf("%T %v\n", s, s)
fmt.Printf("%T %v\n", i, i)
fmt.Printf("%T %v\n", f, f)
}
/* Output:
bool false
string hello
int 10
float64 3.14
*/
当右值声明了类型时,新变量的类型与其相同:
var i int j := i // j 也是一个 int
2.3 短变量声明
func main() {...}:=var:=
importvar:=
package main
import "fmt"
// var 声明变量可以出现在函数外
var b bool = false
// b := false // 报错: syntax error: non-declaration statement outside function body
func main() {
// var 声明变量也可以出现在函数内
var s = "hello"
// 短变量声明 := 只能出现在函数内
i, f := 10, 3.14
fmt.Printf("%T %v\n", b, b)
fmt.Printf("%T %v\n", s, s)
fmt.Printf("%T %v\n", i, i)
fmt.Printf("%T %v\n", f, f)
}
/* Output:
bool false
string hello
int 10
float64 3.14
*/
:==
和普通 var 形式的变量声明语句一样,短变量声明语句也可以用函数的返回值来声明和初始化变量:
// 注意: f 和 err 至少有一个变量之前未被声明过,或者会报错 compile error: no new variables,此时只能使用 = 赋值操作
f, err := os.Open(name)
defer f.Close()
if err != nil {
return err
}
要特别注意短变量声明语句的作用域范围:
package main
import (
"fmt"
"log"
"os"
)
var cwd string
func init() {
cwd, err := os.Getwd() // 不同代码块中的重名变量 cwd
if err != nil {
log.Fatalf("os.Getwd failed: %v", err)
}
// 如果注释掉下面的语句编译不通过,因为内部重声明的 cwd 变量未使用
// compile error: cwd declared and not used
fmt.Printf("Working directory = %s \n", cwd)
}
func main() {
fmt.Printf("%T %q\n", cwd, cwd)
}
/* Output:
Working directory = D:\MyCode\go-in-action
string ""
*/
:=变量重声明
func foo() {
var err error
n, err := io.WriteString(os.Stdout, "Hello, everyone!\n") // err 为变量重声明
...
}
屏蔽:=
package main
import (
"fmt"
"log"
"os"
)
var cwd string
func init() {
var err error
cwd, err = os.Getwd() // 不使用 :=
if err != nil {
log.Fatalf("os.Getwd failed: %v", err)
}
// 即使注释掉下面的语句也不会报错了
fmt.Printf("Working directory = %s \n", cwd)
}
func main() {
fmt.Printf("%T %q\n", cwd, cwd)
}
/* Output:
Working directory = D:\MyCode\go-in-action
string "D:\\MyCode\\go-in-action"
*/
2.4 类型转换
T(v)vTcannot convert v (type a) to type b
package main
import "fmt"
func main() {
// 等价于 var i int = 42
i := 42
fmt.Printf("%T %v\n", i, i)
// 等价于 var f float64 = float64(i)
f := float64(i)
fmt.Printf("%T %v\n", f, f)
}
/* Output:
int 42
float64 42
*/
3. 常量
const
分组
const ( b bool = true s string = "hello" i int = 10 f float64 = 3.14 )
:=
package main
import "fmt"
// const 声明常量可以出现在函数外
const b bool = false
func main() {
// const 声明常量也可以出现在函数内
const s = "hello"
// const i // 报错: missing value in const declaration,常量必须被明确赋值,没有零值的概念
// const i, f := 10, 3.14 // 报错: syntax error: unexpected :=, expecting =
// 类型推导
const i, f = 10, 3.14
fmt.Printf("%T %v\n", b, b)
fmt.Printf("%T %v\n", s, s)
fmt.Printf("%T %v\n", i, i)
fmt.Printf("%T %v\n", f, f)
// i = 20 // 报错: cannot assign to i,常量不可变
}
/* Output:
bool false
string hello
int 10
float64 3.14
*/