zoukankan      html  css  js  c++  java
  • Go变量、常量和作用域

    变量

    变量是几乎所有编程语言中最基本的组成元素。从根本上说,变量相当于是对一块数据存储空间的命名,程序可以通过定义一个变量来申请一块数据存储空间,之后可以通过引用变量名来使用这块存储空间。

    var声明语句可以创建一个特定类型的变量,然后给变量附加一个名字,并且设置变量的初始 值。变量声明的一般语法如下:

    var 变量名字 类型 = 表达式
    定义变量并进行初始化,例如:var name string = "silence"
    
    var 变量名 变量类型
    定义变量使用零值进行初始化,例如:var age int
    
    var 变量名 = 值
    定义变量,变量类型通过值类型进行推导.例如: var isBoy = true
    
    var 变量名 1, 变量名 2 , …, 变量名 n 变量类型
    定义多个相同类型的变量并使用零值进行初始化.例如:var prefix, suffix string
    
    var 变量名 1, 变量名 2 , …, 变量名 n 变量类型 = 值 1, 值 2, …, 值 n
    定义多个相同类型的变量并使用对应的值进行初始化,例如:var prev, next int = 3, 4
    
    var 变量名 1, 变量名 2 , …, 变量名 n = 值 1, 值 2, …, 值 n
    定义多个变量并使用对应的值进行初始化,变量的类型使用值类型进行推导,类型可不相同,例如:var name, age = "silence", 30
    
    批量定义
    var (
        变量名 1 变量类型 1 = 值 1
        变量名 2 变量类型 2 = 值 2 
    )
    定义多个变量并进行初始化,批量复制中变量类型可省略
    例如:
    var (
        name string = "silence"
        age int = 30
    )
    

    初始化表达式可以使用字面量、任何表达式、函数

    package main
    
    import "fmt"
    
    var v0 int
    var v1 int = 1
    var v2 = 2
    
    var v3, v4 int = 3, 4
    
    var v5, v6 = "5", 6
    
    func main() {
    	var (
    		v7 int = 2 + 5
    		v8 int = v2 + v6
    	)
    	fmt.Println(v0, v1, v2, v3, v4, v5, v6, v7, v8)	//0 1 2 3 4 5 6 7 8
    }
    

    简短变量声明

    在函数内部,有一种称为简短变量声明语句的形式可用于声明和初始化局部变量。它以“名字 := 表达式”形式声明变量,变量的类型根据表达式来自动推导。

    t := 0.0
    i := 100	// 注意等号前的冒号
    
    简式声明一般用在func内,要注意的是:全局变量和简式声明的变量尽量不要同名,否则很容易产生偶然的变量隐藏
    

    即使对于经验丰富的Go开发者而言,这也是一个非常常见的陷阱。这个坑很容易挖,但又很难发现。

    func main() {  
        x := 1
        fmt.Println(x)     // 1
        {
            fmt.Println(x) //  1
            x := 2
            fmt.Println(x) //  2
        }
        fmt.Println(x)     //  1 (不是2)
    }
    

    赋值

    想要交换两个变量的值,则可以简单地使用:

    a, b = b, a
    这样省去了使用交换函数的必要
    

    空白标识符

    空白标识符 也被用于抛弃值

    _, b = 5, 7	//5被抛弃
    

    _ 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

    由于Go语言有个强制规定,在函数内一定要使用声明的变量,但未使用的全局变量是没问题的。为了避免有未使用的变量,代码将编译失败,我们可以将该未使用的变量改为 _。

    另外,在Go语言中,如果引入的包未使用,也不能通过编译。有时我们需要引入的包,比如需要init(),或者调试代码时我们可能去掉了某些包的功能使用,你可以添加一个下划线标记符,_,来作为这个包的名字,从而避免编译失败。下滑线标记符用于引入,但不使用。

    package main
    import (  
        _ "fmt"
        "log"
        "time"
    )
    var _ = log.Println
    func main() {  
        _ = time.Now
    }
    

    零值nil

    nil 标志符用于表示interface、函数、maps、slices和channels的“零值”。如果你不指定变量的类型,编译器将无法编译你的代码,因为它猜不出具体的类型。

    package main
    func main() {  
        var x = nil // 错误
        _ = x
    }
    

    字符串不会为 nil

    var s string  = "" // ""是字符串的零值
    var str string	// 也是字符串的零值
    

    常量

    在Go语言中,常量是指编译期间就已知且不可改变的值。常量可以是数值类型(包括整型、浮点型和复数类型)、布尔类型、字符串类型等。

    字面常量

    所谓字面常量(literal),是指程序中硬编码的常量,如:

    -12		//整型 
    
    3.14159265358979323846 // 浮点类型的常量
    
    3.2+12i // 复数类型的常量
    
    true // 布尔类型的常量
    
    "foo" // 字符串常量
    

    在其他语言中,常量通常有特定的类型,比如-12在C语言中会认为是一个int类型的常量。如果要指定一个值为-12的long类型常量,需要写成-12l,这有点违反人们的直观感觉。Go语言的字面常量更接近我们自然语言中的常量概念,它是无类型的。只要这个常量在相应类型的值域范围内,就可以作为该类型的常量,比如上面的常量-12,它可以赋值给int、uint、int32、int64、float32、float64、complex64、complex128等类型的变量。

    常量定义

    常量用于定义不可被修改的的值,需要在编译过程中进行计算,只能为基础的数据类型布尔、数值、字符串,使用 const 进行常量声明,常量声明必须初始化值

    常用语法:

    const 常量名 类型 = 值
    定义常量并进行初始化,例如:const pi float64 = 3.1415926
    
    const 常量名 = 值
    定义常量,类型通过值类型进行推导,例如:const e = 2.7182818
    
    批量定义
    const (
    	常量名 1 类型 1 = 值 1 常量名 2 类型 2 = 值 2 
    	)
    定义多个变量并进行初始化,批量复制中变量类型可省略,并且除了第一个常量值外其他常量可同时省略类型和值,表示使用前一个常量的初始化表达式
    例如:
    const (
        name string = "silence"
        age int = 30
    )
    const (
        name string = "silence"
        desc
    )
    

    常量之间的运算,类型转换,以及对常量调用函数 len、cap、real、imag、complex、unsafe.Sizeof 得到的结果依然为常量

    package main
    
    import "fmt"
    
    const c0 int = 0
    
    const c1 int = 1
    const c2 = 3 -1
    const c3, c4 int = 3, 4
    const c5, c6 = "5", c4 + c2
    
    func main() {
    	const (
    		c7 int = 7
    		c8
    	)
    	fmt.Println(c0, c1, c2, c3, c4, c5, c6, c7, c8)	//0 1 2 3 4 5 6 7 7
    }
    

    枚举iota

    常使用iota生成器用于初始化一系列相同规则的常量,批量声明常量的第一个常量的使用iota进行赋值,此时 iota 被重置为 0,其他常量省略类型和赋值,在每初始化一个常量则加 1

    iota()以内从0开始,如果另一个()内也是iota,则重新从0开始

    const (
    	i1 int = iota
    	i2
    	i3 int = iota
    	i4
    )
    
    func main() {
    	//  枚举
    	const (
    		i5 = iota
    		i6
    		i7 = 7
    		i8 = iota
    		i9
    	)
    
    	fmt.Println(i1, i2, i3, i4, i5, i6, i7, i8, i9)	//0 1 2 3 0 1 7 3 4
    
    }
    

    作用域

    作用域指变量可以使用范围,就近原则。go 语言使用大括号显示的标识作用域范围,大括号内包含一连串的语句,叫做语句块。语句块可以嵌套,语句块内定义的变量不能在语句块外使用

    局部变量

    在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。

    package main
    
    import "fmt"
    
    func main() {
       /* 声明局部变量 */
       var a, b, c int 
    
       /* 初始化参数 */
       a = 10
       b = 20
       c = a + b
    
       fmt.Printf ("结果: a = %d, b = %d and c = %d
    ", a, b, c)	//结果: a = 10, b = 20 and c = 30
    }
    
    

    全局变量

    作用域是全局的(在本包范围内)
    在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用。全局变量可以在任何函数中使用。

    package main
    
    import "fmt"
    
    /* 声明全局变量 */
    var g int
    
    func main() {
    
       /* 声明局部变量 */
       var a, b int
    
       /* 初始化参数 */
       a = 10
       b = 20
       g = a + b
    
       fmt.Printf("结果: a = %d, b = %d and g = %d
    ", a, b, g)	//结果: a = 10, b = 20 and g = 30
    }
    

    简式变量

    使用 := 定义的变量,如果新变量p与那个同名已定义变量 (这里就是那个全局变量p)不在一个作用域中时,那么Go 语言会新定义这个变量p,遮盖住全局变量p。刚开始很容易在此犯错而茫然,解决方法是局部变量尽量不同名,限定标识符使用的范围。

    注意,简式变量只能在函数内部声明使用,但是它可能会覆盖函数外全局同名变量。而且你不能在一个单独的声明中重复声明一个变量,但在多变量声明中这是允许的,而且其中至少要有一个新的声明变量。重复变量需要在相同的代码块内,否则你将得到一个隐藏变量。
    
    如果你在代码块中犯了这个错误,将不会出现编译错误,但应用运行结果可能不是你所期望。所以尽可能避免和全局变量同名。
    

    常见隐式语句块

    	全语句块
    
    ​	包语句块
    
    ​	文件语句块
    
    ​	if、switch、for、select、case 语句块
    
    作用域内定义变量只能被声明一次且变量必须使用,否则编译错误。在不同作用域可定义相同的变量,此时局部将覆盖全局
    
    package main
    
    import "fmt"
    
    func main() {
    	outer := 1
    	{
    		inner := 2
    		fmt.Println(outer, inner)	//1 2
    		outer := 3
    		fmt.Println(outer, inner)	//3 2	寻找由内向外
    	}
    	//fmt.Println(inner)	//使用原则: 子语句块可以使用父语句块中的标识符,父不能用子的
    	fmt.Println(outer)	//1
    }
    

    形式参数

    形式参数会作为函数的局部变量来使用

    package main
    
    import "fmt"
    
    /* 声明全局变量 */
    var a int = 20;
    
    func main() {
       /* main 函数中声明局部变量 */
       var a int = 10
       var b int = 20
       var c int = 0
    
       fmt.Printf("main()函数中 a = %d
    ",  a);	//main()函数中 a = 10
       c = sum( a, b);
       fmt.Printf("main()函数中 c = %d
    ",  c);	//main()函数中 c = 30
    }
    
    /* 函数定义-两数相加 */
    func sum(a, b int) int {
       fmt.Printf("sum() 函数中 a = %d
    ",  a);	//sum() 函数中 a = 10
       fmt.Printf("sum() 函数中 b = %d
    ",  b);	//sum() 函数中 b = 20
    
       return a + b;
    }
    
  • 相关阅读:
    Python 网络编程 C/S建立Socket连接
    odoo 安装配置
    epoll poll select区别
    SyntaxError :invalid syntax Python常见错误
    TypeError: Can't convert 'int' object to str implicitly Python常见错误
    IndexError: list index out of range Python常见错误
    NameError: name 'foo' is not defined Python常见错误
    IndentationError:unexpected indent”、“IndentationError:unindent does not match any outer indetation level”以及“IndentationError:expected an indented block Python常见错误
    TypeError: 'str' object does not support item assignment Python常见错误
    每周总结
  • 原文地址:https://www.cnblogs.com/Otiger/p/13703041.html
Copyright © 2011-2022 走看看