Go语言学习笔记-03变量

Go语言学习笔记-03变量

数据类型

  1. 布尔型,bool
  2. 无符号整形,uint,uint8,unit16,uint32,uint64
  3. 有符号整形,int,int8,int16,int32,int64
  4. 浮点型,float32,float64
  5. 复数型,complex64,complex128
  6. 字符串,string,表示Unicode字符序列
  7. 其他数字类型

    byte,uint8的别名,表示单字节字符

    rune,int32的别名,表示一个Unicode码点

    uintptr,大到足够保存任何指针类型的整形类型

  8. 派生类型

    数组类型,[n]T,表示元素类型为 T 的 n 个元素的数组的类型

    切片类型,[]T,表示元素类型为 T 的可变长度数组的类型

    map类型,键值对的无序集合,类似于其他语言中的字典或哈希表

    结构化类型(struct),由多个字段组成的自定义数据类型

    channel类型,用于在goroutine之间进行同步通信

    指针类型(Pointer),*T

    函数类型,func

    接口类型(interface),表示实现特定方法的类型的类型

变量的声明

go是静态类型语言,声明变量时需要确定好变量的数据类型,不能在同一作用域中声明同名变量

声明有以下几种方式

  1. 仅声明不赋值
var 变量名 数据类型
  1. 声明同时赋值
var 变量名 数据类型 = 值
  1. 声明时缺省变量类型。

    go编译器会根据右边值,自动推导默认类型,若默认类型不是想要的类型,则可以显式类型转换

var 变量名 = 值
var 变量名 = 值
var 变量名 = 数据类型(值)
  1. 同时申明多个变量
var (
变量名1 数据类型1
变量名2 数据类型2
)

var (
变量名1 数据类型1 = 值1
变量名2 数据类型2 = 值2
)
  1. 同一行同时声明多个变量
// 数据类型一致
var 变量名1, 变量名2 数据类型
var 变量名1, 变量名2 数据类型 = 值1, 值2

// 数据类型不一致,采用缺省数据类型方式
var 变量名1, 变量名2 = 值1, 值2
  1. 短变量声明,相当于声明一个变量并赋值

    只能在函数体中使用

    go编译器会根据右边的值,自动推导默认类型,若默认类型不是想要的类型,则可以显式类型转换

变量名 := 值
变量名 := 数据类型(值)
变量名1, 变量名2 := 值1, 值2

变量的赋值

go语言中,类型不同的变量不能赋值给对方,如int32的变量,不能直接赋值给int的变量

空白标识符

空白标识符也称为匿名占位符,使用_表示

在 Go 语言中, 不允许声明未使用的变量或导入语句,这时可以使用空白标识符忽略掉

全局变量

在函数体外声明的变量是全局变量,也称为包级变量

只能使用var方式申明,无法使用短变量声明方式

package main

// 全局变量
var 变量名 数据类型
var 变量名 = 值
var (
   变量名1 = 值1
   变量名2 = 值2
)

func main() {
}

代码示例

ch03/main.go

package main

// 全局变量声明
var globalA1 int
var globalB1 = 1

var (
    globalC1 = 1
    globalC2 = 1
)

func main() {
    // 指定变量类型,没有初始化
    var a1 int

    // 声明并初始化
    var b1 int = 1

    // 变量声明块,批量声明多个变量
    var (
        c1 int    = 128
        c2 int8   = 6
        c3 string = "hello"
        c4 rune   = 'A'
        c5 bool   = true
    )

    // 在一行同时声明多个变量
    var d1, d2, d3 int = 1, 2, 3

    // 在一行同时声明多个变量,类型不一致
    var (
        e1, e2, e3 = "e1", 2, 3.0
    )

    // 省略类型信息的声明,类型为默认类型
    var f1 = 1          // int
    var f1_1 = int32(1) // int32
    var f2 = 1.1        // float64
    var f3 = 'c'        // int32
    var f4 = "d"        // string
    var f5 = true       // bool

    // 短变量声明,申明并赋值,只能在函数体中使用
    // 相当于
    // var a int
    // a = 12
    g1 := 12
    g2 := 'A'
    g3 := "hello"
    g4, g5, g6 := 12, 'A', "hello"

    // 使用空白标识符_忽略掉未使用的变量
    _ = globalA1
    _ = globalB1
    _, _ = globalC1, globalC2
    _ = a1
    _ = b1
    _, _, _, _, _ = c1, c2, c3, c4, c5
    _, _, _ = d1, d2, d3
    _, _, _ = e1, e2, e3
    _, _, _, _, _, _ = f1, f1_1, f2, f3, f4, f5
    _, _, _, _, _, _ = g1, g2, g3, g4, g5, g6

    // 当有新变量申明时,需要使用短变量声明方式
    _, h7 := 0, 0
    _ = h7
}

fmt包

fmt包主要用于向外输出内容和获取输入内容

Println

打印多个值并换行

ch03/fmt/main.go

package main

// 导入fmt包的包路径
import "fmt"

func main() {
    fmt.Println(1, 2, 3)
    fmt.Println(4, 5, 6)
}

上述代码输出

1,2,3
4,5,6

Printf

格式化输出,通过不同的占位符控制输出格式

常用占位符

占位符 说明
%v 值的默认格式表示
%+v 类似%v,但输出结构体时会添加字段名
%#v 值的Go语法表示
%T 打印值的类型
%% 百分号
%d 打印整数
%c 打印对应unicode码值
%s 打印字符串或[]byte
%f 打印浮点数
%t 打印布尔类型

ch03/fmt/main.go

package main

import "fmt"

func main() {
    var a1 = 1
    var a2 = 'a'
    var a3 = true
    fmt.Printf("%d %c %t", a1, a2, a3)
}

上述代码输出

1 a true

默认类型

缺省指定类型时,go会根据右值自动推导其数据类型

类型 备注
整数 int 当数值不在int所能表示的范围内,则需要显式指定数据类型
浮点数 float64
字符 rune int32的别名,与int32等价
字符串 string
true,false bool

ch03/defaulttype/main.go

package main

import "fmt"

func main() {
    var a = 1
    var b = 1.1
    var c = 'a'
    var d = "abc"
    var e = true

    fmt.Printf("变量a的类型为%T\n", a)
    fmt.Printf("变量b的类型为%T\n", b)
    fmt.Printf("变量c的类型为%T\n", c)
    fmt.Printf("变量d的类型为%T\n", d)
    fmt.Printf("变量e的类型为%T\n", e)
}

上述代码输出

变量a的类型为int
变量b的类型为float64
变量c的类型为int32  
变量d的类型为string 
变量e的类型为bool

零值

当只声明不赋值时,不同数据类型的变量会赋予其对应的零值

零值使得变量可以开箱即用,无需显示初始化,即零值可用

内置原生类型 默认值 零值是否可用
所有整形类型 0
浮点类型 0.0
布尔类型 false
字符串类型 ""
指针、接口、切片、channel、map和函数类型 nil
struct 各字段对应类型的零值 看具体字段的类型
数组 填充对应类型的零值

例子

ch03/zerovalue/main.go

package main

import "fmt"

func main() {
    var var1 int
    var var2 float32
    var var3 bool
    var var4 string
    var var5 byte
    var var6 [5]int
    var var7 chan int
    var var8 map[string]int
    var var9 []int
    var var10 func() int

    // 注意有些是用%v,有些是用%#v

    fmt.Printf("int的零值为%v\n", var1)
    fmt.Printf("float32的零值为%v\n", var2)
    fmt.Printf("bool的零值为%v\n", var3)
    fmt.Printf("string的零值为%#v\n", var4)
    fmt.Printf("byte的零值为%v\n", var5)
    fmt.Printf("[5]int的零值为%v\n", var6)

    fmt.Printf("[]int的零值为%#v\n", var9)
    fmt.Printf("chan int的零值为%#v\n", var7)
    fmt.Printf("map的零值为%#v\n", var8)
    fmt.Printf("func() int的零值为%#v\n", var10)
}

上述代码输出

int的零值为0
float32的零值为0                   
bool的零值为false                  
string的零值为""                   
byte的零值为0                      
[5]int的零值为[0 0 0 0 0]          
[]int的零值为[]int(nil)            
chan int的零值为(chan int)(nil)    
map的零值为map[string]int(nil)     
func() int的零值为(func() int)(nil)

可以看出默认值为nil的数据类型类型不是单纯的nil,而是带有具体数据类型的nil,它们是不等价的

作用域

在go语言中,{}包括的内容称之为一个代码块,可以嵌套,外层代码块的作用域包括所有内层代码块,换言之,外层代码块的变量可以在内层代码块内使用,在内层代码块定义与外层代码块同名的变量,会遮蔽外层代码块的同名变量,这种现象称之为变量遮蔽

除了有显示代码块,还有隐式代码块,包括ifforswitch

例子

ch03/variablemasking/main.go

package main

import "fmt"

var a = 1

func main() {
    {
        // 遮蔽包级变量a
        a := 2
        fmt.Println(a) // 2
    }

    if a := 3; a == 3 {
        fmt.Println(a) // 3
    }

    // 等价于上面的if语句,外层的{}就是隐藏的代码块
    {
        a := 3
        if a == 3 {
            fmt.Println(a) // 3
        }
    }

    // 都不影响包级变量a
    fmt.Println(a) // 1
}

笔记地址

github:https://github.com/xianyuyixi...

交流学习

微信号:xianyuyixia

微信公众号:闲渔一下

你可能感兴趣的:(go)