go学习笔记(4)基本类型和声明(3)

1000.png

今天是情人节,愿天下有情人终成眷属👩‍❤️‍👨。

继续学习 go 吧😜,我写的这几篇 go 学习笔记不适合初学 go 的同学,因为都是在关注语言的细节。

我相当于是在大体明白了 go 怎么用怎么写后回过头来看当初忽略的那些细节。初学 go 的话还是建议看官方的 tutorial:https://go.dev/doc/tutorial/getting-started

string、rune

string 是 go 的内置类型,它的零值就是一个空字符串,string 是不可变的。go 支持 Unicode

string 可以用 == 判断是否相等,用 != 判断是否不相等,用 >>=<<= 来比较大小。

string 支持用 + 拼接,虽然用 + 拼接字符串很方便,但是它非常慢,如果有大量字符串要拼接的话会让你怀疑电脑是不是死机了。

如果要拼接大量字符串的话,可以用strings.Builder

1
2
3
4
5
6
7
8
9
var builder strings.Builder
strs := []string{"Every moment", " of each day,",
" loving and", " missing you ", "dominates ",
"every inch of ", "my brain. "}
for _, str := range strs {
builder.WriteString(str)
}
builder.WriteString("\n")
fmt.Println(builder.String())

输出:Every moment of each day, loving and missing you dominates every inch of my brain.

rune 类型用于表示各种字符,上回讲过,rune 就是 int32 的一个别名。

显式类型转换

go 的类型转换和其他语言类似,用类型(变量),就可以把变量转换成另一个类型了。go不支持隐式类型转换,如果两个类型不同的变量相互运算会出错。

1
2
3
4
5
6
7
8
9
10
var x int = 200
var y int32 = 14
var z int64 = int64(x)+int64(y)
var a float32 = 2.1
var b float64 = 0.04
var c float64 = float64(a) + b
var m int64 = z + int64(c)
fmt.Println(z)
fmt.Println(c)
fmt.Println(m)

输出:

1
2
3
214
2.1399999046325684
216

因为 go 只支持显式类型转换,所以其他的类型无法当成布尔类型来用,如果想将其他类型转换成布尔类型,那就只能通过比较运算符比较后得到(==!=><<=>=

var 与 :=

go 虽然是一门强类型的静态语言,但在书写时总是会有种这是一门动态语言的错觉。

与大多数其他语言不同,go 在声明变量时会把变量的名字放在前面,而把变量的类型放在后面。

一开始会有些不习惯,但时间长了发现这样会使得代码更加整洁易读。

最基本的变量声明方式是:

1
2
var x int // x会被自动初始化为0
var x int = 214 // x被赋值为214

如果变量的类型与要赋值的字面量默认类型相同则在声明的时候就不用写类型了。

1
var x = 214

这里注意,虽然go不支持变量的隐式转换,但对于字面量可以认为它是支持隐式转换的,或者认为字面量只有在进行赋值时才确定类型(想想也很合理,214一看它的样子就会认为它是int,但你一定说它是个float64也没毛病)。

一次声明多个变量:

1
2
3
4
5
6
7
8
9
10
11
12
var x, y int
// 定义多个同类型变量
var x, y int = 2, 14
// 定义多个不同类型的变量
var a, b = 214, "Valentine's Day"
var (
x int
y = 2
z int = 14
d, e = 214, "Valentine's Day"
f, g string
)

除了用 var 还有一种更加偷懒的定义变量的方法 :=

1
2
3
4
5
var x = 214
x := 214

var x, y = 214, "Valentine's Day"
x, y := 1314, "Valentine's Day"

是不是越来越像动态语言了😄,简直太方便了,平时定义变量的时候用的最多的就是这种写法。

:= 只能用于定义新的变量,它不是赋值,如果变量已经声明了,再用 := 的话会编译错误。但有一个例外,如果 := 左边同时含有未声明和已声明的变量名时,那它会定义未声明的变量,并对已声明的变量赋值:

1
2
x := 214
x, y := 214, "Valentine's Day"

一些不适合用 := 的地方

  • 初始化为零值时最好用var x int定义,这样语义最明确
  • 定义变量时如果字面量的默认类型与你要的不同就不要用
  • 当你想重用外面作用域的变量的同时又要创建新的变量时,很可能想重用的那个变量也会被创建成一个同名的变量😅,我表达的比较绕😂。看例子:
    1
    2
    3
    4
    5
    6
    var e float64 = 214
    func() {
    n, e := 214, 214.214
    fmt.Println(n, e)
    }()
    fmt.Println(e)
    输出:
    1
    2
    214 214.214
    214
    go 是支持闭包的,在这个例子里,匿名函数中的 e 与它外面的 e 是不同的,尽管外面已经有一个变量 e 了但是:=还是在匿名函数内创建了一个新的变量 e

江达小记