首页 > 其他分享 >go--变量、常量、作用域

go--变量、常量、作用域

时间:2023-11-07 18:13:50浏览次数:33  
标签:Println name 作用域 fmt var -- go main iota

变量

变量可以通过变量名访问。Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。

声明变量的一般形式是使用 var 关键字:

var 变量名 变量类型

也可以一次声明多个变量

var 变量名1,变量名2 变量类型
package main

import "fmt"

func main() {
   var a string = "zouzou"  // 定义了个变量 a,类型为 string,值为 邹邹
   fmt.Println(a)

   var b, c int = 1, 2 // 定义了两个变量 b 和 c,类型为 int,b 的值为 1,c 的值为 2
   fmt.Println(b, c)
}

结果

zouzou
1 2

如果没有初始化,则变量默认为零值

零值就是变量没有做初始化时系统默认设置的值。

package main

import "fmt"

func main() {

   // 声明一个变量并初始化
   var a = "zouzou"
   fmt.Println(a)

   // 没有初始化就为零值
   var b int
   fmt.Println(b)

   // bool 零值为 false
   var c bool
   fmt.Println(c)
}

结果

zouzou
0
false

零值的有

  • 数值类型(包括complex64/128)为 0

  • 布尔类型为 false

  • 字符串为 ""(空字符串)

  • 以下几种类型为 nil

var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error 是接口

类型推导

如果声明了一个变量,没有声明类型,会根据值进行类型推导

package main

import "fmt"

func main() {
   var d = true // 没有声明类型,会自动推导
   fmt.Println(d)
}

结果

true

如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误,格式

v_name := value

例如

var intVal int 
intVal :=1 // 这时候会产生编译错误,因为 intVal 已经声明,不需要重新声明

直接使用下面的语句即可:

intVal := 1 // 此时不会产生编译错误,因为有声明新的变量,因为 := 是一个声明语句

intVal := 1 相等于

var intVal int 
intVal =1 

可以将 var f string = "zouzou" 简写为 f := "zouzou":

package main

import "fmt"

func main() {
   f := "zouzou" // 等价于 var f string = "zouzou"
   fmt.Println(f)
}

 还有其他的声明方式

package main

var x, y int
var ( // 这种因式分解关键字的写法一般用于声明全局变量
   a int
   b bool
)

var c, d int = 1, 2
var e, f = 123, "hello"

//这种不带声明格式的只能在函数体中出现
//g, h := 123, "hello"

func main() {
   g, h := 123, "hello"
   println(x, y, a, b, c, d, e, f, g, h)
}

使用 := 赋值操作符

我们知道可以在变量的初始化时省略变量的类型而由系统自动推断,声明语句写上 var 关键字其实是显得有些多余了,因此我们可以将它们简写为 a := 50 或 b := false。

a 和 b 的类型(int 和 bool)将由编译器自动推断。

这是使用变量的首选形式,但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值。使用操作符 := 可以高效地创建一个新的变量,称之为初始化声明。

常量

常量是一个简单值的标识符,在程序运行时,不会被修改的量。

常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

常量的定义格式:

const 常量名 [type] = value

你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。

  • 显式类型定义: const b string = "abc"
  • 隐式类型定义: const b = "abc"
package main

import "fmt"

func main() {
   const LENGTH int = 10           // 常量 LENGTH
   const WIDTH int = 5             // 常量 WIDTH
   var area int                    // 变量
   const a, b, c = 1, false, "zou" //多重赋值

   area = LENGTH * WIDTH
   fmt.Printf("面积为 : %d", area)
   println()
   println(a, b, c)
}

结果

面积为 : 50
1 false zou

 在常量组中,如果不指定类型和值,则和上一行的类型还有值都一样

package main

import "fmt"

func main() {
   // 常量组如果不指定类型和值,则和上一行的类型的值一样
   const (
      x int = 10
      y
      a = "abc"
      b
   )
   fmt.Print(x, y, a, b)
}

结果

10 10 abc abc

iota

  • iota,特殊常量,可以认为是一个可以被编译器修改的常量。
  • iota 只能在常量组中使用
  • 不同的 const 块中互相不影响
  • 从第一行开始,每一行 iota 都会加 1

iota 可以被用作枚举值:

const (
    a = iota // iota = 0
    b = iota // iota = 1,每一行 iota 加 1
    c = iota // iota = 2,每一行 iota 加 1
)

第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;所以 a=0, b=1, c=2 可以简写为如下形式:

const (
    a = iota
    b
    c
)

看下面的例子

package main

import "fmt"

func main() {
   const (
      a    = iota       // 0
      b    = 10         // iota = 1
      c                 // 和上一行的值相等
      d, e = iota, iota // iota = 3,所以 d、e 都等于 3
      f    = iota       // iota = 4
   )
   fmt.Println(a, b, c, d, e, f)
}

 结果

0 10 10 3 3 4

例子二

package main

import "fmt"

func main() {
   const (
      a = iota // 0
      b        // 1
      c        // 2
      d = "ha" //独立值,iota = 3
      e        //没有值和上一行的值相等 "ha"   iota = 4
      f = 100  //iota = 5
      g        //没有值和上一行的值相等 100  iota = 6
      h = iota // 7,恢复计数
      i        // 8
   )
   fmt.Println(a, b, c, d, e, f, g, h, i)
}

 输出结果

0 1 2 ha ha 100 100 7 8

作用域

package main

import "fmt"

func main() {
   name := "zouzou" // 只在当前的 {} 里有效
   fmt.Println(name)
   if true {
      fmt.Println(name)
      age := 18 // 只在当前的 {} 里有效
      fmt.Println(age)
      name := "邹邹"
      fmt.Println(name)
   }
   println(name)
   //fmt.Println(age) 错误,因为 age 是局部变量

}

结果

zouzou
zouzou
18
邹邹
zouzou
  • 全局变量,未写在函数中的变量称为全局变量;不可以使用v1:=xx方式进行简化;可以基于因式分解方式声明多个变量;
  • 局部变量,编写在 {} 里面的变量;可以使用任意方式简化;可以基于因式分解方式声明多个变量;
package main

import "fmt"

// 全局变量(不能以省略的方式)
var school string = "北京大学" // 可以
//var school = "北京大学"   // 可以
//school := "北京大学"         // 不可以,不能简写

var ( // 全局变量
   v1 = 123
   v2 = "你好"
   v3 int
)

func main() {

   name := "zouzou" // 局部变量
   fmt.Println(name)
   if true {
      age := 18    // 局部变量
      name := "邹邹" // 局部变量
      fmt.Println(age)
      fmt.Println(name)
   }
   fmt.Println(name)
   fmt.Println(school)
   fmt.Println(v1, v2, v3)
}

结果

zouzou
18
邹邹
zouzou
北京大学
123 你好 0

赋值与内存相关

name := "zouzou"

如上代码,定义了一个变量,会在内存中开辟出一块地址,赋值给变量 name

name := "zouzou"
nickname := name

如上如果定义了一个变量 name,在定义了一个变量 nickname,将 name 赋值给 nickname。在 go 中,会将 name 的拷贝一份,如下

package main

import "fmt"

func main() {
   name := "zouzou"
   nickName := name
   fmt.Println(name, &name)         // &name 是 name 变量的内存地址
   fmt.Println(nickName, &nickName) // &nickName 是 nickName 变量的内存地址
}

结果

zouzou 0xc000010250
zouzou 0xc000010260

可以看到,我们把一个变量赋值给另一个变量后,内存地址是不一样的,因为会新开辟一块内存地址。不像 python 语言,会指向同一块内存地址

例子

package main

import "fmt"

func main() {
   name := "zouzou"
   nickName := name
   fmt.Println(name, &name)
   fmt.Println(nickName, &nickName)

   name = "daliu" // 修改了name 的值,但是内存地址还是之前的,只是在之前的内存地址上修改了值
   fmt.Println(name, &name)
   fmt.Println(nickName, &nickName) // 值类型,会拷贝一份
}

结果

zouzou 0xc000010250
zouzou 0xc000010260
daliu 0xc000010250
zouzou 0xc000010260

可以看到,当我们改变变量的值后,内存地址没有变,只是改变了内存地址里对应的数据。而赋值后的变量 nickName 是不会变的,因为是新开辟的内存地址,没有改变这个内存地址的值

注意:使用 int、string、bool、数组 这几种数据类型时,如果遇到变量的赋值则会拷贝一份。【值类型】

标签:Println,name,作用域,fmt,var,--,go,main,iota
From: https://www.cnblogs.com/zouzou-busy/p/16088301.html

相关文章

  • 机器学习之使用seaborn绘制各类图形
    使用seaborn绘制单双变量,类别散点图,箱型图,小提琴图去更直观的观察数据的分布情况在单变量图中使用displot,参数如下 双变量关系图使用joinplot,参数如下图 类别散点图使用stripplot(),参数如下 小提琴图和箱型图类似,一个使用violinplot(),另一个使用boxplot(),参数基本一......
  • ArcGIS API for JavaScript入门
    arcgis官网:https://arcgis.fenxianglu.cn/docs/load.html一、集成到应用----@arcgis/core方式1、引入ArcGISAPIforJavaScriptyarnadd@arcgis/core或者指定安装版本yarnadd@arcgis/[email protected]如果提示:'yarn'不是内部或外部命令,也不是可运行的程序或批处理文件......
  • CentOS怎么安装最新版本docker
    环境查看[root@localhost~]#cat/etc/redhat-releaseCentOSLinuxrelease7.9.2009(Core)[root@localhost~]#uname-aLinuxlocalhost.localdomain3.10.0-1160.el7.x86_64#1SMPMonOct1916:18:59UTC2020x86_64x86_64x86_64GNU/Linux安装docker#更新源......
  • centOS6.5 gitlab安装 记录
    很久很久以前的服务器系统版本是centOS6.5感觉会有坑上篇yum源下载问题已解决记录下安装gitLab的过程:安装C编译器yum-yinstallgcc(查下系统里面是否有安装)1.安装配置依赖项sudoyuminstall curl openssh-serveropenssh-clientspostfixcronie2.启动postfix邮......
  • Linux软件安装
    1、命令   su用户名切换用户,从管理员切换到普通用户,是不需要密码,否则需要密码,exit返回原来的用户2、文件权限通过ll查看权限,有10个字母,分成4组第1个字符:表示文件的类型  -普通文件,d目录,l链接第2、3、4个字符表示文件所有者的权限第5、6、7个字符表示文件所有者......
  • 正则表达式-r'\[.*\]'和r'[.*]'的区别
    则表达式r'[.*]'实际上会匹配包含任何一个字符*或.或*的字符串。这不是想要的结果。希望匹配方括号[]中的任意字符,并且要匹配多个字符。要匹配方括号[]中的任意字符,并匹配多个字符,你应该使用r'\[.*\]',其中\[匹配左方括号,.*匹配任意字符(包括数字、字母等等),然后\]......
  • C-B-T-I-添加量表数据
    Sql模板set@hid='eec28119-78e4-4023-8f2a-98ce070f91ff';set@gid='aa2e97fg-7bad-49c2-a993-164222b164cc';set@gaugeName='Yale-Brown强迫症状量表';set@Remark='Yale-Brown强迫症状量表';set@ScoreMultiple=1;set@now=NOW();DELETE......
  • Element Plus 动态表单验证
    <divv-for="(item,index)informList":key="index"><el-form:ref="(el)=>{formRefs(el)}":model="item"><el-form-item><el-inputv-model="item.name"></el-input......
  • k8s-服务网格实战-配置 Mesh(灰度发布)
    在上一篇k8s-服务网格实战-入门Istio中分享了如何安装部署Istio,同时可以利用Istio实现gRPC的负载均衡。今天我们更进一步,深入了解使用Istio的功能。从Istio的流量模型中可以看出:Istio支持管理集群的出入口请求(gateway),同时也支持管理集群内的mesh流量,也就是集群内......
  • 3.3 万能Map
     <insertid="addUser",parameterType="map"> insertintomybatis.user(id,pwd)values(#{userId},#{passWord});</insert>//MapintaddUser2(Map<String,object>map);@TestpublicvoidaddUser2(){  Sqlsessionsqlsession=......