go 介绍
1.静态语言类型,但有动态语言感觉(开发效率高)
2.运行效率高
3.语言层面支持并发
4.丰富的第三方库
适合做
服务器编程
编程
go 语言以包作为管理单位
每个文件必须声明包
程序必须有一个main包
语句结尾无分号
变量赋值初始化
package main
import (
"fmt"
)
func main() {
//变量,程序运行期间,可以改变的量
//1、声明格式 var 变量名 类型, 变量声明了,必须要使用
//2、只是声明没有初始化的变量,默认值为0
//3、同一个{}里,声明的变量名是唯一的
var a int
fmt.Println("a = ", a)
//4、可以同时声明多个变量
//var b, c int
a = 10 //变量的赋值
fmt.Println("a = ", a)
//2、变量的初始化,声明变量时,同时赋值
var b int = 10 //初始化,声明变量时,同时赋值(一步到位)
b = 20 //赋值, 先声明,后赋值
fmt.Println("b = ", b)
//3、自动推导类型,必须初始化,通过初始化的值确定类型(常用)
c := 30
//%T打印变量所属的类型
fmt.Printf("c type is %T\n", c)
}
打印结果:
a = 0
a = 10
b = 20
c type is int
Println 与 Printf 的区别
package main
import (
"fmt"
)
func main() {
a := 10
//一段一段处理,自动加换行
fmt.Println("a = ", a)
//格式化输出, 把a的内容放在%d的位置
// "a = 10\n" 这个字符串输出到屏幕,"\n"代表换行符
fmt.Printf("a = %d\n", a)
b := 20
c := 30
fmt.Println("a = ", a, ", b = ", b, ", c = ", c)
fmt.Printf("a = %d, b = %d, c = %d\n", a, b, c)
}
打印结果:
a = 10
a = 10
a = 10 , b = 20 , c = 30
a = 10, b = 20, c = 30
匿名变量,Go函数可以返回多个值
package main
import (
"fmt"
)
//go函数可以返回多个值
func test() (a, b, c int) {
return 1, 2, 3
}
func main() {
// a := 10
// b := 20
// c := 30
a, b := 10, 20
//交换2个变量的值
var tmp int
tmp = a
a = b
b = tmp
fmt.Printf("a = %d, b = %d\n", a, b)
i, j := 10, 20
i, j = j, i
fmt.Printf("i = %d, j = %d\n", i, j)
i = 10
j = 20
//_匿名变量,丢弃数据不处理, _匿名变量配合函数返回值使用,才有优势
tmp, _ = i, j
fmt.Println("tmp = ", tmp)
var c, d, e int
c, d, e = test() //return 1, 2, 3
fmt.Printf("c = %d, d = %d, e = %d\n", c, d, e)
_, d, e = test() //return 1, 2, 3
fmt.Printf("d = %d, e = %d\n", d, e)
}
打印结果:
a = 20, b = 10
i = 20, j = 10
tmp = 10
c = 1, d = 2, e = 3
d = 2, e = 3
常量
package main
import "fmt"
func main() {
//变量:程序运行期间,可以改变的量, 变量声明需要var
//常量:程序运行期间,不可以改变的量,常量声明需要const
const a int = 10
//a = 20 //err, 常量不允许修改
fmt.Println("a = ", a)
const b = 11.2 //没有使用:=
fmt.Printf("b type is %T\n", b)
fmt.Println("b = ", b)
}
打印结果:
a = 10
b type is float64
b = 11.2
iota 枚举
package main
import "fmt"
func main() {
//1、iota常量自动生成器,每个一行,自动累加1
//2、iota给常量赋值使用
const (
a = iota //0
b = iota //1
c = iota //2
)
fmt.Printf("a = %d, b = %d, c = %d\n", a, b, c)
//3、iota遇到const,重置为0
const d = iota
fmt.Printf("d = %d\n", d)
//4、可以只写一个iota
const (
a1 = iota //0
b1
c1
)
fmt.Printf("a1 = %d, b1 = %d, c1 = %d\n", a1, b1, c1)
//5、如果是同一行,值都一样
const (
i = iota
j1, j2, j3 = iota, iota, iota
k = iota
)
fmt.Printf("i = %d, j1 = %d, j2 = %d, j3 = %d, k = %d\n", i, j1, j2, j3, k)
}
打印结果:
a = 0, b = 1, c = 2
d = 0
a1 = 0, b1 = 1, c1 = 2
i = 0, j1 = 1, j2 = 1, j3 = 1, k = 2
字符与字符串的区别,单引号是字符,双引号是字符串
package main
import "fmt"
func main() {
var ch byte
var str string
//字符
//1、单引号
//2、字符,往往都只有一个字符,转义字符除外'\n'
ch = 'a'
fmt.Println("ch =", ch)
//字符串
//1、双引号
//2、字符串有1个或多个字符组成
//3、字符串都是隐藏了一个结束符,'\0'
str = "a" // 由'a'和'\0'组成了一个字符串
fmt.Println("str = ", str)
str = "hello go"
//只想操作字符串的某个字符,从0开始操作
fmt.Printf("str[0] = %c, str[1] = %c\n", str[0], str[1])
}
打印结果:
ch = 97
str = a
str[0] = h, str[1] = e
复合类型 complex128
package main //必须有一个main包
import "fmt"
func main() {
var t complex128 //声明
t = 2.1 + 3.14i //赋值
fmt.Println("t = ", t)
//自动推导类型
t2 := 3.3 + 4.4i
fmt.Printf("t2 type is %T\n", t2)
//通过内建函数,取实部和虚部
fmt.Println("real(t2) = ", real(t2), ", imag(t2) = ", imag(t2))
}
打印结果:
t = (2.1+3.14i)
t2 type is complex128
real(t2) = 3.3 , imag(t2) = 4.4
格式化输出,%v匹配所有类型
package main //必须有一个main包
import "fmt"
func main() {
a := 10
b := "abc"
c := 'a'
d := 3.14
//%T操作变量所属类型
fmt.Printf("%T, %T, %T, %T\n", a, b, c, d)
//%d 整型格式
//%s 字符串格式
//%c 字符个数
//%f 浮点型个数
fmt.Printf("a = %d, b = %s, c = %c, d = %f\n", a, b, c, d)
//%v自动匹配格式输出
fmt.Printf("a = %v, b = %v, c = %v, d = %v\n", a, b, c, d)
}
打印结果:
int, string, int32, float64
a = 10, b = abc, c = a, d = 3.140000
a = 10, b = abc, c = 97, d = 3.14
基本类型转换
package main //必须有一个main包
import "fmt"
func main() {
//这种不能转换的类型,叫不兼容类型
var flag bool
flag = true
fmt.Printf("flag = %t\n", flag)
//bool类型不能转换为int
//fmt.Printf("flag = %d\n", int(flag))
//0就是假,非0就是真
//整型也不能转换为bool
//flag = bool(1)
var ch byte
ch = 'a' //字符类型本质上就是整型
var t int
t = int(ch) //类型转换,把ch的值取出来后,转成int再给t赋值
fmt.Println("t = ", t)
}
打印结果:
flag = true
t = 97
if 语句
package main //必须有一个main包
import "fmt"
func main() {
s := "123"
//if和{就是条件,条件通常都是关系运算符
if s == "123" { //左括号和if在同一行
fmt.Println("左手一个妹子,右手一个大妈")
}
//if支持1个初始化语句, 初始化语句和判断条件以分号分隔
if a := 10; a == 10 { //条件为真,指向{}语句
fmt.Println("a == 10")
}
}
打印结果:
左手一个妹子,右手一个大妈
a == 10
遍历字符串,range 迭代 列表
package main //必须有一个main包
import "fmt"
func main() {
str := "abc"
//通过for打印每个字符
for i := 0; i < len(str); i++ {
fmt.Printf("str[%d]=%c, ", i, str[i])
}
fmt.Println()
//迭代打印每个元素,默认返回2个值: 一个是元素的位置,一个是元素本身
for i, data := range str {
fmt.Printf("str[%d]=%c, ", i, data)
}
fmt.Println()
for i := range str { //第2个返回值,默认丢弃,返回元素的位置(下标)
fmt.Printf("str[%d]=%c, ", i, str[i])
}
fmt.Println()
for i, _ := range str { //第2个返回值,默认丢弃,返回元素的位置(下标)
fmt.Printf("str[%d]=%c, ", i, str[i])
}
fmt.Println()
}
打印结果:
str[0]=a, str[1]=b, str[2]=c,
str[0]=a, str[1]=b, str[2]=c,
str[0]=a, str[1]=b, str[2]=c,
str[0]=a, str[1]=b, str[2]=c,
goto 的使用
package main //必须有一个main包
import "fmt"
func main() {
//goto可以用在任何地方,但是不能夸函数使用
fmt.Println("1111111111111")
goto End //goto是关键字, End是用户起的名字, 他叫标签
fmt.Println("2222222222222")
End:
fmt.Println("3333333333333")
}
打印结果:
1111111111111
3333333333333
函数,不定参数
package main //必须有一个main包
import "fmt"
func test(args ...int) {
for _, data := range args {
fmt.Printf("%d, ", data)
}
}
func main() {
test(1, 2, 3, 4)
}
打印结果:
1, 2, 3, 4,
将不定参数传递到另一个函数
package main //必须有一个main包
import "fmt"
func test(args ...int) {
test2(args...)
}
func test2(args ...int){
for _, data := range args{
fmt.Printf("%d, ", data)
}
}
func main() {
test(1, 2, 3, 4)
}
打印结果:
1, 2, 3, 4,
含有返回值的函数,函数名首字母小写为private,大写为public
package main //必须有一个main包
import "fmt"
//给返回值起一个变量名,go推荐写法
//常用写法
func test(a int, b int) (result int) {
result = a + b
return
}
func main() {
result := test(11, 22)
fmt.Println(result)
}
打印结果:
33
泛型,多态
package main //必须
import "fmt"
type FuncType func(int, int) int
//实现加法
func Add(a, b int) int {
return a + b
}
func Minus(a, b int) int {
return a - b
}
func Mul(a, b int) int {
return a * b
}
//回调函数,函数有一个参数是函数类型,这个函数就是回调函数
//计算器,可以进行四则运算
//多态,多种形态,调用同一个接口,不同的表现,可以实现不同表现,加减乘除
//现有想法,后面再实现功能
func Calc(a, b int, fTest FuncType) (result int) {
fmt.Println("Calc")
result = fTest(a, b) //这个函数可以后面再实现
return
}
func main() {
//a := Calc(1, 1, Add)
//a := Calc(1, 1, Minus)
a := Calc(1, 1, Mul)
fmt.Println("a = ", a)
}
打印结果:
Calc
a = 0
闭包的作用域需要十分注意,对于变量来说,只有闭包还在使用它,这些变量就还会存在。
package main //必须
import "fmt"
//函数的返回值是一个匿名函数,返回一个函数类型
func test02() func() int {
var x int //没有初始化,值为0
return func() int {
x++
return x * x
}
}
func main() {
//返回值为一个匿名函数,返回一个函数类型,通过f来调用返回的匿名函数,f来调用闭包函数
//它不关心这些捕获了的变量和常量是否已经超出了作用域
//所以只有闭包还在使用它,这些变量就还会存在。
f := test02()
fmt.Println(f()) //1
fmt.Println(f()) //4
fmt.Println(f()) //9
fmt.Println(f()) //16
}
打印结果:
1
4
9
16
defer 的用法,执行顺序:先进后出
package main //必须
import "fmt"
func test(a int){
result := 100 / a
fmt.Println(result)
}
func main() {
defer fmt.Println("1111111111")
defer fmt.Println("2222222222")
test(0)
defer fmt.Println("3333333333")
}
打印结果:
2222222222
1111111111
panic: runtime error: integer divide by zero
goroutine 1 [running]:
defer 与 匿名函数的配合使用
package main //必须
import "fmt"
func main() {
a := 10
b := 20
defer func(a, b int) {
fmt.Printf("a = %d, b = %d\n", a, b)
}(10, 20) //()代表调用此匿名函数, 把参数传递过去,已经先传递参数,只是没有调用
a = 111
b = 222
fmt.Printf("外部:a = %d, b = %d\n", a, b)
}
打印结果:
外部:a = 111, b = 222
a = 10, b = 20
Go 函数 变量作用域
局部变量
package main //必须
import "fmt"
func main() {
定义在{}里面的变量就是局部变量,只能在{}里面有效
执行到定义变量那句话,才开始分配空间,离开作用域自动释放
作用域,变量其作用的范围
//a = 111
{
i := 10
fmt.Println("i = ", i)
}
//i = 111
if flag := 3; flag == 3 {
fmt.Println("flag = ", flag)
flag变量范围只在 if 中
}
变量 flag 不存在
//flag = 4
}
切片作为函数参数时是引用传递,