变量定义 #
变量要先声明,再赋值.即先定义后使用
单个变量格式:
var 变量名 类型名
var 变量名 类型名 = 值
var 变量名 = 值 //推导类型写法1
变量名 := 值 //推导类型写法2,简短方式定义
// 声明:
var a int // 声明 int 类型的变量,默认值0
var b [10]int // 声明 int 类型数组,每个单元默认值为0
var c []int // 声明 int 类型的切片,默认值为nil,长度为0
切片追加值:c = append(c, 110)
var d *int // 声明 int 类型的指针,空指针,默认值为nil
//为空指针赋值,需要再分配空间,如:b = new(int); *b = 12
var d2 *int = new(int) // 或者使用 变量名 := new(数据类型) 定义,如:d2 := new(int)
var e struct{
e1 int
}
var f map[string]int
var f2 map[string]int = make(map[string]int)
var g func(a int) int //一个int参数且返回int类型的函数变量
var g2 func() //无参无返回值函数变量
var h interface{} //定义接收任何类型的变量
//普通变量赋值、修改值
a = 10
//数组、切片修改单元值
b[0] = 10
//map变量赋值、修改值
f2["name"] = "good"
// 同时声明与赋值
var a1 = 10 //推导变量类型方式1
a2 := 10 //推导变量类型方式2,简短方式定义
a3,b3,c4,d3 := 1,2,true,"def"
var a4 int = 100
//指针变量
d:=new(int) //方法参数接收指针变量写法: func a(d *int){ }
//上面声明等价 var d *int = new(int)
*d = 123 //赋值
fmt.Println(d) //0xc000016600
fmt.Println(*d) //123
变量批量定义 #
格式1:var 变量名1,变量名2,变量名N 类型
示例: var a, b,c int; //定义a、b、c变量的类型均为int
格式2:var 变量名1,变量名2,变量名N = 值1,值2,值N //这种方式省略了类型,则是根据值自动判断类型(类型推断),结合系统位数推算类型
格式3:var 变量名1,变量名2,变量名N 类型 = 值1,值2,值N
示例:var b ,c int = 100, 5
格式4:变量名1,变量名2,变量名N := 值1,值2,值N //这种是省略var写法,且只能在函数体中使用,根据值自动判断类型
格式5:在函数体内和函数体外均可使用
var (
变量名1 数据类型
变量名2 数据类型
变量名3,变量名4,变量名5 数据类型
变量名6,变量名7,变量名8 数据类型 = 值1,值2,值N
变量名N 数据类型 = 值
)
示例:
var (
x int
y float32
z string = "hello"
x1,y1 int = 10,20
)
匿名变量 #
匿名变量: _
使用示例: var username, _ = getUserInfo(123)
func GetName()(firstname, lastname, fullname string) {
return "zhang", "san", "张三"
}
firstname, _, nickname := GetName()
变量初始值(默认值、零值) #
1.整型和浮点型变量默认值为0
2.字符串变量默认值为空
3.bool型变量默认值为false
4.切片,map字典,函数,指针变量,通道、接口 默认值为nil
5.数组的默认值(零值)取决于数组的类型,示例:var a [2]int //默认值为 [0 0]
示例:
var a *int
var b []int
var c map[string]int
var d chan int
var e func(string) int
var f error //error是接口类型
fmt.Println(a,b,c,d,e,f) //<nil> [] map[] <nil> <nil> <nil>
全局变量与局部变量名称可以相同 #
package main
import "fmt"
//声明全局变量
var abc float32 = 3.14
func main() {
//声明局部变量
var abc int = 99
fmt.Printf("abc = %d\n", abc)
}
//以上代码输出 abc = 99
备注:1.Go语言程序中全局变量与局部变量名称可以相同,但是函数体内的局部变量会被优先考虑
2. 全局变量名与全局变量名不能相同。
局部变量名与局部变量名不能相同。
变量函数示例 #
package main
import "fmt"
func main() {
var abc func() = foo
//abc = foo
abc()
}
func foo() {
fmt.Println("hello world")
}
执行完成,代码打印:hello world
变量作用域 #
变量作用域: 1. 全局作用域(全局变量):在程序整个生命周期有效,在函数外部定义的,如: var a int = 100
2. 局部变量,分两种: 1)函数内定义,2)语句块内定义
方法的参数及返回值变量也是局部变量
示例:
package main
import "fmt"
//全局变量
var a1 int = 8
func main() {
var a2 int = 9 //局部变量
fmt.Println(a2)
hi()
}
func hi() {
var b1 string = "hi" //局部变量
fmt.Printf("hi方法中b1=%v \n",b1)
if a1>1 { //在函数中使用全局变量a1
var b2 int = 100
fmt.Printf("hi方法if语句块中b2=%v \n", b2)
}
//fmt.Println(b2) //这里报语法错误,因为b2只在if语句块中有效
if i:=110; i<12 {
fmt.Printf("i=%v\n", i)
} else {//i变量在整个if-elseif-else语句块内有效,局部变量
fmt.Printf("else i=%v \n", i)
}
for j:=1; j<5;j++ { //j变量只在for语句块内有效,局部变量
fmt.Println(j)
}
//fmt.Println(j) //这里报语法错误,因为j变量在for初始语句块中声明,作用范围为for语句块内
}
获取变量的类型 #
1. 使用func Sprintf(format string, a ...interface{}) string函数
示例:t := fmt.Sprintf("%T", v)
封装成独立方法如下:
//获取变量or值的类型
func typeof(v interface{}) string {
return fmt.Sprintf("%T", v)
}
2. 反射方式获取
封装独立方法:
func typeof02(v interface{}) string {
return reflect.TypeOf(v).String()
}
3. 类型断言
var x interface{} //定义interface类型变量,即存储任意类型的数据变量
x = 123 //给x变量赋值
switch i := x.(type) {
case nil:
fmt.Printf(" x 的类型 :%T",i)
case int:
fmt.Printf("x 是 int 型")
case float64:
fmt.Printf("x 是 float64 型")
case func(int) float64:
fmt.Printf("x 是 func(int) 型")
case bool, string:
fmt.Printf("x 是 bool 或 string 型" )
default:
fmt.Printf("未知型")
}