Go基础|第3章:基本类型、变量与常量

  • 原创
  • Madman
  • /
  • /
  • 0
  • 5659 次阅读

Golang.jpg

Synopsis: Go 语言将数据类型分为四类:基本类型、复合类型、引用类型和接口类型,本文仅简单介绍下布尔型、字符串、整型、浮点型、复数等基本类型,各类型的详细说明可以参考《The Go Programming Language》,然后学习如何声明变量和常量

1. 基本类型

Go 的基本类型有三类:

  1. 布尔型 bool: 只有 truefalse 两种值,支持以下逻辑运算符
    • &&
    • ||
    • !
  2. 字符串 string: 是一个不可改变的字节序列,文本字符串通常被解释为采用 UTF8 编码的 Unicode code point(rune)序列。注意: 内置的 len() 函数返回一个字符串中的字节数目(不是 rune 字符数目)
  3. 数值型
    • 整数 int/int8/int16/int32/int64/uint/uint8/uint16/uint32/uint64/uintptr/byte/rune
    • 浮点数 float32/float64
    • 复数 complex64/complex128

其中 byteuint8 的别名。runeint32 的别名,表示一个 Unicode code point(比如字符 𪸿 的 Unicode 码点为 U+2AE3F,十六进制转换为十进制后的整数为 175679):

// 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"。单引号表示一个 rune 字符,比如 '𪸿'

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 */ 

其它零值:

  • 引用类型(function、slice、map、channel、pointer 和 interface)对应的零值是 nil
  • array 或 struct 等聚合类型对应的零值是每个元素或字段所对应的类型的零值

零值初始化机制可以确保每个声明的变量总是有一个良好定义的值,因此在 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 "" */ 

虽然 cwd 在外部已经声明过,但是 := 语句声明的 cwd 和 err 是新的局部变量,与外部的 cwd 属于不同的代码块,所以可以重名(不同代码块中的重名变量)。而 变量重声明 是在同一个代码块内,且只用于 := 语句中,比如:

func foo() { var err error n, err := io.WriteString(os.Stdout, "Hello, everyone!\n") // err 为变量重声明 ... } 

因为内部声明的 cwd 将 屏蔽 外部的声明,所以上面的代码并不会正确更新包级声明的 cwd 变量值。为了避免出现类似潜在的问题,最直接的方法是通过单独声明 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) 的意思是,将值 v 的类型转换为 T 类型,如果两个类型之间无法转换时,将报错:cannot 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 */ 
分类: Go Basic
标签: := bool const int string var
未经允许不得转载: LIFE & SHARE - 王颜公子 » Go基础|第3章:基本类型、变量与常量

分享

作者

作者头像

Madman

如需 Linux / Python 相关问题付费解答,请按如下方式联系我

0 条评论

暂时还没有评论.