Go语言变量作用域

作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。 

Go 语言中变量可以在三个地方声明:

• 函数内定义的变量称为局部变量 
• 函数外定义的变量称为全局变量 
• 函数定义中的变量称为形式参数 

接下来让我们具体了解局部变量、全局变量和形式参数。 

局部变量

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

全局变量

在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用。 

注:Go 语言程序中全局变量与局部变量名称可以相同,但是函数内的局部变量会被优先考虑。

形式参数

形式参数会作为函数的局部变量来使用。实例如下: 

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\n",  a); 
   c = sum( a, b);   
   fmt.Printf("main()函数中 c = %d\n",  c); 
} 
 
/* 函数定义-两数相加 */ 
func sum(a, b int) int {   
   fmt.Printf("sum() 函数中 a = %d\n",  a); 
   fmt.Printf("sum() 函数中 b = %d\n",  b); 
 
   return a + b; 
}

以上代码的执行结果为:

main()函数中 a = 10 
sum() 函数中 a = 10
sum() 函数中 b = 20 
main()函数中 c = 30

初始化局部和全局变量

不同类型的局部和全局变量默认值为: 数据类型 初始化默认值 

go实现全局sessionid_指针变量


 

Go语言数组

Go 语言提供了数组类型的数据结构。 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形、字符串或者自定义类型。 相对于去声明 number0,number1,...,andnumber99 的变量,使用数组形式 numbers[0], numbers[1] ..., numbers[99]更加方便且易于扩展。 数组元素可以通过索引(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。 

go实现全局sessionid_指针变量_02

声明数组
 Go 语言数组声明需要指定元素类型及元素个数,语法格式如下: 

var variable_name [SIZE] variable_type

以上为一维数组的定义方式。数组长度必须是整数且大于 0。 

例如以下定义了数组 balance 长度为 10 类型为 float32: 

var balance [10] float32

初始化数组

如下演示了数组的初始化:

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

初始化数组中 {} 中的元素个数不能大于 [] 中的数字。 如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小。

访问数组元素

数组元素可以通过索引(位置)来读取。格式为数组名后加中括号,中括号中为索引的值。例如: 

float32 salary = balance[9]

以上实例读取了数组 balance 第 10 个元素的值。 以下演示了数组完整操作(声明、赋值、访问)的实例: 

package main 
 
import "fmt" 
 
func main() {  
   var n [10]int /* n 是一个长度为 10 的数组 */ 
   var i,j int 
 
   /* 为数组 n 初始化元素 */          
   for i = 0; i < 10; i++ {    
       n[i] = i + 100 /* 设置元素为 i + 100 */ 
   } 
 
   /* 输出每个数组元素的值 */ 
   for j = 0; j < 10; j++ { 
      fmt.Printf("Element[%d] = %d\n", j, n[j] ) 
   } 
}

以上代码执行结果为:

Element[0] = 100 
Element[1] = 101 
Element[2] = 102 
Element[3] = 103 
Element[4] = 104 
Element[5] = 105 
Element[6] = 106 
Element[7] = 107 
Element[8] = 108 
Element[9] = 109

数组作为函数的参数

如果想传递一个一维数组作为参数到一个函数中,必须声明函数形式参数以下面两 种方式的其中一种,两个声明方法都产生类似的结果,因为每个方式都告诉编译器 要接收一个整数数组。类似的方式,可以传递多维数组作为形式参数。 

方法-1 形式参数作为一个已知大小数组如下:

void myFunction(param [10]int) 
{ 

}

方法二

形式参数作为一个为指导大小的数组如下:

void myFunction(param []int) 
{ 

}

现在,考虑下面的函数,它将数组作为参数和另一个指定数组大小的参数,并基于 传递的参数,计算数组传递的数组中每个元素的平均值返回,如下: 

func getAverage(arr []int, int size) float32 
{ 
   var i int 
   var avg, sum float32   
 
   for i = 0; i < size; ++i { 
      sum += arr[i] 
   } 
 
   avg = sum / size 
 
   return avg; 
}

主函数调用:

package main 
 
import "fmt" 
 
func main() { 
   /* an int array with 5 elements */ 
   var  balance = []int {1000, 2, 3, 17, 50} 
   var avg float32 
 
   /* pass array as an argument */ 
   avg = getAverage( balance, 5 ) ; 
 
   /* output the returned value */ 
   fmt.Printf( "Average value is: %f ", avg ); 
} 
func getAverage(arr []int, size int) float32 { 
   var i,sum int 
   var avg float32   
 
   for i = 0; i < size;i++ { 
      sum += arr[i] 
   } 
 
   avg = float32(sum / size) 
 
   return avg; 
}

结果为:

Average value is: 214.400000

Go语言指针

Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务。 我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。 Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。

什么是指针

指针是一个变量,其值是另一个变量的地址,即存储器位置的直接地址。类似变量或常量一样,必须要先声明一个指针,然后才能使用它来存储任何变量地址。指针变量声明的一般形式是 类似于变量和常量,在使用指针前你需要声明指针。指针声明格式为:

var var_name *var-type
  • var-type 为指针类型 
  • var_name 为指针变量名 
  • *号用于指定变量是作为一个指针 

如何使用指针

指针使用流程:

  1. 定义指针变量
  2. 为指针变量赋值
  3. 访问指针变量种指向的值

在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。 

package main 
 
import "fmt" 
 
func main() {   
    var a int= 20   /* 声明实际变量 */   
    var ip *int        /* 声明指针变量 */ 
  
    ip = &a  /* 指针变量的存储地址 */ 
 
    fmt.Printf("a 变量的地址是: %x\n", &a  ) 
 
   /* 指针变量的存储地址 */   
    fmt.Printf("ip 变量储存的指针地址: %x\n", ip ) 
 
   /* 使用指针访问值 */   
    fmt.Printf("*ip 变量的值: %d\n", *ip ) 
}

以上实例执行输出结果为:

a 变量的地址是: 20818a220 
ip 变量储存的指针地址: 20818a220 
*ip 变量的值: 20

 Go空指针

当一个指针被定义后没有分配到任何变量时,它的值为 nil。 nil 指针也称为空指针。 nil 在概念上和其它语言的 null、None、nil、NULL 一样,都指代零值或空值。 一个指针变量通常缩写为 ptr。 

package main 
 
import "fmt" 
 
func main() { 
   var  ptr *int 
 
   fmt.Printf("ptr 的值为 : %x\n", ptr  ) 
}

结果为:

ptr 的值为 : 0

Go指针数组

package main 
import "fmt" 
 
const MAX int = 3 
 
func main() { 
   a := []int{10,100,200} 
   var i int 
   for i = 0; i < MAX; i++ { 
      fmt.Printf("Value of a[%d] = %d\n", i, a[i] ) 
   } 
}

结果为:

Value of a[0] = 10 
Value of a[1] = 100 
Value of a[2] = 200

可能有一种情况,当想要维护一个数组,它可以存储指向 int 或字符串或任何其 他可用的数据类型的指针。下面是一个指向整数的指针数组的声明: 

var ptr [MAX]*int;

这里将 ptr 声明为一个 MAX 整数的指针数组。 因此,ptr 中的每个元素现在保存 一个指向 int 值的指针。以下示例使用三个整数,它们将存储在指针数组中,如 下所示:

package main 
 
import "fmt" 
const MAX int = 3 
func main() { 
   a := []int{10,100,200} 
   var i int 
   var ptr [MAX]*int; 
 
   for  i = 0; i < MAX; i++ { 
      ptr[i] = &a[i] /* assign the address of integer. */ 
   } 
 
   for  i = 0; i < MAX; i++ { 
      fmt.Printf("Value of a[%d] = %d\n", i,*ptr[i] ) 
   } 
}

结果为:

Value of a[0] = 10 
Value of a[1] = 100 
Value of a[2] = 200

指向指针的指针 

指向指针的指针是多重间接的形式或指针链。通常,指针包含变量的地址。当定义 指向指针的指针时,第一个指针包含第二个指针的地址,它指向包含实际值的位 置,如下所示。 

go实现全局sessionid_go实现全局sessionid_03

作为指向指针的指针的变量必须如此声明。这是通过在其名称前面添加一个星号 (*)来实现的。 例如,以下是一个指向 int 类型的指针的声明

var ptr **int;

当目标值由指向指针的指针间接指向时,访问该值需要应用两个星号(**)运算符

package main 
 
import "fmt" 
 
func main() { 
 
   var a int 
   var ptr *int 
   var pptr **int 
   a = 3000 
   /* take the address of var */ 
   ptr = &a 
   /* take the address of ptr using address of operator & */ 
   pptr = &ptr 
   /* take the value using pptr */ 
   fmt.Printf("Value of a = %d\n", a ) 
   fmt.Printf("Value available at *ptr = %d\n", *ptr ) 
   fmt.Printf("Value available at **pptr = %d\n", **pptr) 
}

结果为:

Value of var = 3000 
Value available at *ptr = 3000 
Value available at **pptr = 3000

传递指针到函数

Go 编程语言允许传递一个指针到函数中。 为此,只需将函数的参数声明为指针类 型。 看看下面一个简单的例子,传递了两个指针给一个函数,并在函数里面改变它们的 值,这个值反映在调用函数中: 

package main 
 
import "fmt" 
 
func main() { 
   /* local variable definition */ 
   var a int = 100 
   var b int= 200 
 
   fmt.Printf("Before swap, value of a : %d\n", a ) 
   fmt.Printf("Before swap, value of b : %d\n", b ) 
 
   /* calling a function to swap the values. 
   * &a indicates pointer to a ie. address of variable a and  
   * &b indicates pointer to b ie. address of variable b. 
   */ 
   swap(&a, &b); 
 
   fmt.Printf("After swap, value of a : %d\n", a ) 
   fmt.Printf("After swap, value of b : %d\n", b ) 
} 
 
func swap(x *int, y *int) { 
   var temp int 
   temp = *x    /* save the value at address x */ 
   *x = *y      /* put y into x */ 
   *y = temp    /* put temp into y */ 
}

结果为:

Before swap, value of a :100 
Before swap, value of b :200 
After swap, value of a :200
After swap, value of b :100