《Go语言精进之路》读书笔记 | 使用无类型常量简化代码

Posted COCOgsta

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Go语言精进之路》读书笔记 | 使用无类型常量简化代码相关的知识,希望对你有一定的参考价值。

书籍来源:《Go语言精进之路:从新手到高手的编程思想、方法和技巧》

一边学习一边整理读书笔记,并与大家分享,侵权即删,谢谢支持!

附上汇总贴:《Go语言精进之路》读书笔记 | 汇总_COCOgsta的博客-CSDN博客


在Go语言中,常量还兼具特殊的作用。

9.1 Go常量溯源

Go中所有与常量有关的声明都通过const来进行,例如:

// $GOROOT/src/os/file.go
const (
    O_RDONLY int = syscall.O_RDONLY
    O_WRONLY int = syscall.O_WRONLY
    O_RDWR   int = syscall.O_RDWR
    O_APPEND int = syscall.O_APPEND
    ...
)
复制代码

上面代码通过const声明了一组常量,可以将这组常量视为枚举的整型常量。绝大多数情况下,Go常量在声明时并不显式指定类型,比如:

// $GOROOT/src/io/io.go
const (
    SeekStart   = 0
    SeekCurrent = 1
    SeekEnd     = 2
)
复制代码

无类型常量是Go语言在语法设计方面的一个“微创新”,也是“追求简单”设计哲学的又一体现。

9.2 有类型常量带来的烦恼

Go要求,两个类型即便拥有相同的底层类型(underlying type),也仍然是不同的数据类型:

type myInt int

func main() 
    var a int = 5
    var b myInt = 6
    fmt.Println(a + b) // 编译器会给出错误提示:invalid operation: a + b (mismatched  types int and myInt)

复制代码

要解决上面的编译错误,必须进行显式类型转换:

type myInt int

func main() 
    var a int = 5
    var b myInt = 6
    fmt.Println(a + int(b)) // 输出:11

复制代码

有类型常量与变量混合在一起进行运算求值时也要遵循这一要求:

type myInt int
const n myInt = 13
const m int = n + 5        // 编译器错误提示:cannot use n + 5 (type myInt) as type  int in const initializer

func main() 
    var a int = 5
    fmt.Println(a + n)     // 编译器错误提示:invalid operation: a + n (mismatched  types int and myInt)

复制代码

唯有进行显式类型转换才能让上面的代码正常工作:

type myInt int
const n myInt = 13
const m int = int(n) + 5

func main() 
    var a int = 5
    fmt.Println(a + int(n)) // 输出:18

复制代码

有类型常量给代码简化带来了麻烦,但这也是Go语言对类型安全严格要求的结果。

9.3 无类型常量消除烦恼,简化代码

字面值无须显式类型转换就可以直接赋值给对应的三个自定义类型的变量,而Go的无类型常量就拥有像字面值这样的特性。该特性使得无类型常量在参与变量赋值和计算过程时无须显式类型转换,从而达到简化代码的目的:

const (
    a  = 5
    pi = 3.1415926
    s  = "Hello, Gopher"
    c  = 'a'
    b  = false
)

type myInt int
type myFloat float32
type myString string

func main() 
    var j myInt = a
    var f myFloat = pi
    var str myString = s
    var e float64 = a + pi

    fmt.Println(j)    // 输出:5
    fmt.Println(f)                // 输出:3.1415926
    fmt.Println(str)              // 输出:Hello, Gopher
    fmt.Printf("%T, %v\\n", e, e)  // float64, 8.1415926

复制代码

无类型常量使得Go在处理表达式混合数据类型运算时具有较大的灵活性,代码编写也有所简化,我们无须再在求值表达式中做任何显式类型转换了。

无类型常量也拥有自己的默认类型:无类型的布尔型常量、整数常量、字符常量、浮点数常量、复数常量、字符串常量对应的默认类型分别为bool、int、int32(rune)、float64、complex128和string。

当常量被赋值给无类型变量、接口变量时,常量的默认类型对于确定无类型变量的类型及接口对应的动态类型是至关重要的。示例如下。

const (
    a = 5
    s = "Hello, Gopher"
)

func main() 
    n := a
    var i interface = a

    fmt.Printf("%T\\n", n)         // 输出:int
    fmt.Printf("%T\\n", i)         // 输出:int
    i = s
    fmt.Printf("%T\\n", i)         // 输出:string

以上是关于《Go语言精进之路》读书笔记 | 使用无类型常量简化代码的主要内容,如果未能解决你的问题,请参考以下文章

《Go语言精进之路》读书笔记 | 了解string实现原理并高效使用

《Go语言精进之路》读书笔记 | 在init函数中检查包级变量的初始状态

《Go语言精进之路》读书笔记 | 了解map实现原理并高效使用

《Go语言精进之路》读书笔记 | 尽量定义零值可用的类型

《Go语言精进之路》读书笔记 | 理解Go语言表达式的求值顺序

《Go语言精进之路》读书笔记 | 汇总