声明变量
var identifier type
var:声明变量关键字
identifier:变量名称
type:变量类型
批量声明及初始化
var (
name string="dcl"
phone int =123123
b bool=true
)
短变量声明
//只能在函数内部
dog :="sense"
多返回值以及匿名变量
func main() {
_, age := getIden()//下划线代表匿名变量
println(age)
}
func getIden() (string, int) {//多返回值
return "tom", 30
}
go语言常量
//go语言常量赋值
func main() {
const pi float32 = 3.1415926
const pi2 = 3.1415926
const (
pi3 = 3.14
pi4 = 3.1415
)
const pia, pib = 3.14, 3.141
}
iota
const (
a = iota //0
b //1
c //2
d = "ha" //独立值,iota += 1
e //"ha" iota += 1
f = 100 //iota +=1
g //100 iota +=1
h = iota //7,恢复计数
_ //跳过 iota +=1
i //9
)
fmt.Println(a, b, c, d, e, f, g, h, i)
运行结果:
0 1 2 ha ha 100 100 7 9
应用场景:枚举时
位运算符
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
Go 语言支持的位运算符如下表所示。假定 A 为60,B 为13:
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与运算符"&"是双目运算符。 其功能是参与运算的两数各对应的二进位相与。 | (A & B) 结果为 12, 二进制为 0000 1100 |
| | 按位或运算符"|"是双目运算符。 其功能是参与运算的两数各对应的二进位相或 | (A | B) 结果为 61, 二进制为 0011 1101 |
^ | 按位异或运算符"^"是双目运算符。 其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 | (A ^ B) 结果为 49, 二进制为 0011 0001 |
<< | 左移运算符"<<"是双目运算符。左移n位就是乘以2的n次方。 其功能把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。 | A << 2 结果为 240 ,二进制为 1111 0000 |
>> | 右移运算符">>"是双目运算符。右移n位就是除以2的n次方。 其功能是把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数。 | A >> 2 结果为 15 ,二进制为 0000 1111 |
var a uint = 60 /* 60 = 0011 1100 */
var b uint = 13 /* 13 = 0000 1101 */
var c uint = 0
c = a & b /* 12 = 0000 1100 */
fmt.Printf("第一行 - c 的值为 %d\n", c)
c = a | b /* 61 = 0011 1101 */
fmt.Printf("第二行 - c 的值为 %d\n", c)
c = a ^ b /* 49 = 0011 0001 */
fmt.Printf("第三行 - c 的值为 %d\n", c)
c = a << 2 /* 240 = 1111 0000 */
fmt.Printf("第四行 - c 的值为 %d\n", c)
c = a >> 2 /* 15 = 0000 1111 */
fmt.Printf("第五行 - c 的值为 %d\n", c)
运算结果:
第一行 - c 的值为 12
第二行 - c 的值为 61
第三行 - c 的值为 49
第四行 - c 的值为 240
第五行 - c 的值为 15
其他运算符
运算符 | 描述 | 实例 |
---|---|---|
& | 返回变量存储地址 | &a; 将给出变量的实际地址。 |
* | 指针变量。 | *a; 是一个指针变量 |
func main() {
var a int = 4
var b int32
var c float32
var ptr *int
/* 运算符实例 */
fmt.Printf("第 1 行 - a 变量类型为 = %T\n", a)
fmt.Printf("第 2 行 - b 变量类型为 = %T\n", b)
fmt.Printf("第 3 行 - c 变量类型为 = %T\n", c)
/* & 和 * 运算符实例 */
ptr = &a /* 'ptr' 包含了 'a' 变量的地址 */
fmt.Printf("a 的值为 %d\n", a)
fmt.Printf("*ptr 为 %d\n", *ptr)
fmt.Printf("ptr为 %d\n", ptr)
}
程序结果:
第 1 行 - a 变量类型为 = int
第 2 行 - b 变量类型为 = int32
第 3 行 - c 变量类型为 = float32
a 的值为 4
*ptr 为 4
ptr为 824633827480
条件语句
大致和其他语言相同
fallthrough:使用 fallthrough 会强制执行后面的 case 语句,fallthrough 不会判断下一条 case 的表达式结果是否为 true。
func main() {
grade := 80
switch grade {
case 50:
fmt.Println("50fen")
fallthrough
case 60:
fmt.Println("60fen")
fallthrough
case 70:
fmt.Println("70fen")
case 80:
fmt.Println("80fen")
fallthrough
case 90:
fmt.Println("90fen")
default:
fmt.Println("6、默认 case")
}
}
结果:
80fen
90fen
从以上代码输出的结果可以看出:如果 case 带有 fallthrough,程序会继续执行下一条 case,且它不会去判断下一个 case 的表达式是否为 true。
select
select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。
select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。
其他待补充
循环语句
//和 C 语言的 for 一样:
for init; condition; post { }
//和 C 的 while 一样:
for condition { }
//和 C 的 for(;;) 一样:
for { }
-
init: 一般为赋值表达式,给控制变量赋初值;
-
condition: 关系表达式或逻辑表达式,循环控制条件;
-
post: 一般为赋值表达式,给控制变量增量或减量。
for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:
for key, value := range oldMap {
newMap[key] = value
}
以上代码中的 key 和 value 是可以省略。
如果只想读取 key,格式如下:
for key := range oldMap
或者这样:
for key, _ := range oldMap
如果只想读取 value,格式如下:
for _, value := range oldMap
goto
func main() {
/* 定义局部变量 */
var a int = 10
LOOP:
for a <= 20 {
if a == 15 {
a += 1
goto LOOP
}
fmt.Printf("%T"+" %v\n", a, a)
a++
}
}
运行结果
int 10
int 11
int 12
int 13
int 14
int 16
int 17
int 18
int 19
int 20
go语言函数
func function_name( [parameter list] ) [return_types] {
函数体
}
-
func:函数由 func 开始声明
-
function_name:函数名称,参数列表和返回值类型构成了函数签名。
-
parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
-
return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
-
函数体:函数定义的代码集合。
不过注意值传递和引用传递
func swap(x *int, y *int) {
var temp int
temp = *x /* 保持 x 地址上的值 */
*x = *y /* 将 y 值赋给 x */
*y = temp /* 将 temp 值赋给 y */
}
Go 语言数组
var variable_name [SIZE] variable_type
常用赋值方法
func main() {
//赋值方法
var a = [4]int{1, 2, 3, 4}
b := [4]string{"asd", "ssss"}
c := [...]float32{1.2, 3123.2, 123.2}
for i := 0; i < len(a); i++ {
fmt.Printf("%d", a[i])
}
for _, x := range b {
println(x)
}
for _, f := range c {
println(f)
}
}
如果数组长度不确定,可以使用 ... 代替数组的长度,编译器会根据元素个数自行推断数组的长度:
1234asd
ssss
+1.200000e+000
+3.123200e+003
+1.232000e+002
注意
当函数使用数组时,都是值传递,不会改变原有数组,要改变原有数组使用切片(slice)
go语言指针
Go 语言的取地址符是 &
func main() {
var a int = 20
var adress *int
adress = &a
fmt.Printf("%d\n", a)
fmt.Printf("%x\n", &a)
fmt.Printf("%x\n", adress)
}
运行结果
20
c00001a098
c00001a098
go语言结构体
主要创建结构体的方法如下所示
type Books struct {
title string
author string
subject string
book_id int
//定义的结构体如果只在当前包内使用,结构体的属性不用区分大小写。如果想要被其他的包引用,那么结构体名和属性的首字母需要大写。
}
//如果有结构方法,和上述规则
func main() {
// 创建一个新的结构体
fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
}
如果要访问结构体成员,需要使用点号 . 操作符。
可以像其他数据类型一样将结构体类型作为参数传递给函数,但是为值传递,不改变原有数据。
可以定义指向结构体的指针类似于其他指针变量,格式如下:
var struct_pointer *Books
type hero struct {
name string
age int
Level int
}
type superman struct {
hero //继承
high int
}
func (a hero) getname() {
fmt.Printf("%s\n", a.name)
}
func (a *hero) setname(name string) {
a.name = name
}
func (man superman) fly() {
fmt.Printf(man.name + " is flying")
}
func main() {
hero1 := hero{name: "xiaoming", age: 20, Level: 5}
hero1.getname()
hero1.setname("ycc")
fmt.Printf("%v\n", hero1)
sup := superman{hero{"zhangsan", 12, 3}, 3}
fmt.Printf("%v\n", sup)
sup.fly()
}
Go 语言切片(Slice)
创建切片
func main() {
//创建切片,如果括号里指定大小就是数组
numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}//也可以make([]T, length, capacity)创建切片
printSlice(numbers)
/* 打印原始切片 */
fmt.Println("numbers ==", numbers)
/* 打印子切片从索引1(包含) 到索引4(不包含)*/
fmt.Println("numbers[1:4] ==", numbers[1:4])
/* 默认下限为 0*/
fmt.Println("numbers[:3] ==", numbers[:3])
/* 默认上限为 len(s)*/
fmt.Println("numbers[4:] ==", numbers[4:])
numbers1 := make([]int, 0, 5) //通过内置函数 make() 初始化切片
printSlice(numbers1)
/* 打印子切片从索引 0(包含) 到索引 2(不包含) */
numbers1 = numbers[:2]
printSlice(numbers1)
/* 打印子切片从索引 2(包含) 到索引 5(不包含) */
//capacity 为 7 是因为 number3 的 ptr 指向第三个元素, 后面还剩 2,3,4,5,6,7,8, 所以 cap=7。
number3 := numbers[2:5]
printSlice(number3)
}
func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}
判断空切片用 numbers == nil
append() 和 copy() 函数
func main() {
var numbers []int
printSlice(numbers)
/* 向切片添加一个元素 */
numbers = append(numbers, 1)
printSlice(numbers)
/* 同时添加多个元素 */
numbers = append(numbers, 2, 3, 4)
printSlice(numbers)
/* 创建切片 numbers1 是之前切片的两倍容量*/
numbers1 := make([]int, len(numbers), (cap(numbers))*2)
/* 拷贝 numbers 的内容到 numbers1 */
copy(numbers1, numbers)
printSlice(numbers1)
numbers1 = append(numbers1, 54)
printSlice(numbers1)
}
func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}
Go 语言范围(Range)
在for循环中提到过range的用法,可以对 slice、map、数组、字符串等进行迭代循环
func main() {
a := [8]int{11, 21, 31, 41, 51, 61, 71, 81}
for i, i2 := range a {
fmt.Printf("%d %d\n", i, i2)
}
}
运行结果
0 11
1 21
2 31
3 41
4 51
5 61
6 71
7 81
Go 语言Map(集合)
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
函数传递map时为引用传递
func main() {
//创建集合
//var countryCapitalMap map[string]string
countryCapitalMap := make(map[string]string)
/* map插入key - value对,各个国家对应的首都 */
countryCapitalMap["France"] = "巴黎"
countryCapitalMap["Italy"] = "罗马"
countryCapitalMap["Japan"] = "东京"
countryCapitalMap["India "] = "新德里"
/*使用键输出地图值 */
for country := range countryCapitalMap {
fmt.Println(country, "首都是", countryCapitalMap[country])
}
/*查看元素在集合中是否存在 */
capital, ok := countryCapitalMap["American"] /*如果确定是真实的,则存在,否则不存在 */
//fmt.Println(capital)
//fmt.Println(ok)
if ok {
fmt.Println("American 的首都是", capital)
} else {
fmt.Println("American 的首都不存在")
}
}
delete() 函数
func main() {
//创建集合
//var countryCapitalMap map[string]string
countryCapitalMap := make(map[string]string)
/* map插入key - value对,各个国家对应的首都 */
countryCapitalMap["France"] = "巴黎"
countryCapitalMap["Italy"] = "罗马"
countryCapitalMap["Japan"] = "东京"
countryCapitalMap["India "] = "新德里"
fmt.Println(countryCapitalMap["France"])
delete(countryCapitalMap, "France")
if countryCapitalMap["France"] == "" {
fmt.Println("不存在")
} else {
fmt.Println(countryCapitalMap["France"])
}
}
面向多态的实现(interface)
多态的必要条件
-
要有继承;
-
要有重写;
-
父类引用指向子类对象。
package main
// 本质是指针
type animal interface {
sleep()
eat()
run()
}
// 具体的类
type dog struct {
color string
}
func (this dog) sleep() {
println("dog is sleeping")
}
func (this dog) eat() {
println("dog eat")
}
func (this dog) run() {
}
func (this *dog) getColor() string {
return this.color
}
// 具体的类
type cat struct {
color string
}
func (this cat) sleep() {
println("cat is sleeping")
}
func (this cat) eat() {
println("cat eat")
}
func (this cat) run() {
}
func (this *cat) getColor() string {
return this.color
}
func main() {
var am animal //接口的数据类型
am = dog{color: "red"}
am.sleep() //多态的现象
am.eat()
am = cat{color: "brown"}
am.sleep()
am.eat()
}
Interface万能接口与类型断言机制
func myfunc(args interface{}) {
println("dasdasd")
//关于args如何区分类型
value, ok := args.(string)//断言机制!
if !ok {
println("args 不是string类型")
} else {
fmt.Printf("值:%s 类型:%T", value, value)
}
}
func main() {
test := "lslsls"
myfunc(test)
}
结果:
值:lslsls 类型:string标签:语言,int,fmt,语法,numbers,func,Printf,go,string From: https://www.cnblogs.com/sukidakara/p/16821751.html