Golang 简介 golang指的是google公司推出的一种高效、可靠、简洁并具有强大并行处理能力的编程语言.
Golang的设计理念是简介性、高效性和安全性。它的语法简洁且易于理解,使得程序员可以更快地进行开发和维护代码。这也使得Golang成为一种非常适合于开发网络应用和大数据处理的语言。
与其他流行的编程语言相比,Golang在许多方面都具有优势。首先,它有一个独特的 Goroutine 机制,这使得并发编程变得更加容易。其次,它有一个强大的标准库,其中包括了许多有用的工具和功能,例如网络编程、加密、解析和操作系统相关的函数。此外,Golang还支持交叉编译功能,让程序员能够在不同的平台上轻松地构建和运行应用程序。
Golang 安装 Windows系统安装步骤
下载golang安装包
访问golang官方网站 ,下载适用于Windows系统的golang安装包。
安装golang
双击下载的安装包,按照安装向导的提示完成golang的安装。
配置环境变量
将golang的安装目录添加到系统的PATH环境变量中,以便在命令行中能够直接访问golang相关的命令。
Mac 系统安装步骤
安装go 软件 brew install go
查看golang 当前版本 go version
配置环境变量(只需要设置GOPATH和GOROOT 环境变量) Mac brew 安装基本GOROOT 已经设置好了,只需要配置GOPATH 加入环境变量 查看当前golang环境 执行 go env
设置GOPATH 及环境变量(GOPATH 是工作目录)
(1).先创建工作目录 本人位置家目录下go文件夹 $ mkdir $HOME/work
(2).添加环境变量 我使得zsh,如果使用bash 请编辑~/.bash_profile文件
编辑 vim .zshrc
添加两条:
1 2 3 export GOPATH=$HOME /go 工作目录 export PATH = $PATH :$GOPATH /bin 加入环境变量,$PATH 不可省略
执行 source ~/.zshrc
或者 下载压缩包安装(创建工作目录文件) 下载golang 发布版本tar 包 地址:https://golang.org/dl/ (可查看文档查找)
Golang 目录介绍 go整个目录就是一个SDK,包括了一些基础的工具,如编译,运行,测试等。
api目录:包含了各种API接口。 bin目录:包含了各种 go 命令行工具(go.gofmt)。 src目录:包含了源码文件
Golang 代码
创建一个 test.go 文件。
1 2 3 4 5 6 7 8 9 package main import ( "fmt" ) func main () { fmt.Println("hellow Go!" ) }
对源文件 test.go 文件进行编译: go build test.go
=> 会生成一个可执行文件:test
(二进制可执行文件,在windos下生成test.exe
)可以直接运行(无需环境也可运行)。 【编译的文件也可以另外指定名字 : go build -o 新的名字xxx test.go
】
通过go run test.go
运行代码可以直接帮我们编译执行源文件。 (相比较 go build
运行速度更快 因为省去编译的过程)
语法的注意事项
源文件以 go 为扩展名。
参与的执行入口时main()函数。
严格区分大小写。
方法由一条条语句构成,每一个语句后不需要分号(Go语言会在每行后自动添加分号)
Go编译器时一行行进行编译的,因此我们一行就写一条语句,不能多条语句写在同一个,否则报错.
定义变量或者import的包没有使用到,代码就无法编译通过。
大括号都是成对出现的,缺一不可。
通过命令完成格式化操作: gofmt test.go
格式化代码,但只会展示格式后的代码,不会修改源文件。如果需要修改源文件,需要使用gofmt -w test.go
命令。
API (应用程序编程接口) http://docscn.studygolang.com/pkg/ 当前没有中文,需要用到翻译软件。
变量 声明 -> 赋值 -> 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package main import "fmt" func main () { var age int age = 10 fmt.Println("age = " , age) var age2 int = 19 fmt.Println("age2 = " , age2) fmt.Println("hellow Go!" ) }
变量的4种使用方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package mainimport "fmt" var n4 = 100 var ( n10 = 200 n11 = 300 n12 = "你好呀" ) func main () { var num int = 10 fmt.Println(num) var num2 int fmt.Println(num2) var num3 = "hello world" fmt.Println(num3) sex := "男" fmt.Println(sex) fmt.Println("---------------------------------------" ) var n1,n2,n3 int fmt.Println(n1) fmt.Println(n2) fmt.Println(n3) var n5,n6,n7 = 10 ,"luo" ,37.9 fmt.Println(n5) fmt.Println(n6) fmt.Println(n7) n8,n9 := 7.2 ,"hello" fmt.Println(n8) fmt.Println(n9) fmt.Println("---------------------------------------" ) fmt.Println(n4) fmt.Println(n10) fmt.Println(n11) fmt.Println(n12) }
变量的类型 数值类型 : 整型类型(int,byte,uint,uint8,uint16,uint32,uint64,int8,int16,int32,int64),浮点类型(float32,float64)字符类型 :(没有单独的字符类型,使用byte来保存耽搁字母字符)布尔类型 : bool字符串类型 :string
派生数据类型/复杂数据类型 : 指针(pointer)、函数(function)、管道(channel)、数组(array)、切片(slice)、结构体(struct)、接口(interface)、map。
扩展: 举例 int8 有符合 占1字节 数值范围 -128~127 ps: 127 怎么算出来的? 首先正数 所以首字肯定为 0, 然后最大值 后面肯定都是1 ,所以是 01111111 01111111 -> 二进制转为十进制 : 12^6 + 1 2^5 + 12^4 + 1 2^3 + 12^2 + 1 2^1 + 1*2^0 = 127
ps: -127怎么算出来的? 首先负数 所以首字肯定为 1, 然后最大值 后面肯定都是0 ,所以是 10000000
10000000 -> 负数的二进制 减1:01111111 取反:100000000 —》得到一个正数 2^7=128 加负号:-
整型类型 1 2 3 4 5 6 7 8 9 10 package mainimport "fmt" var nmu int8 = 129 func main () { fmt.Println(num) }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport ( "fmt" "unsafe" ) func main () { var num int8 = 120 fmt.Println(num) var num2 = 127 fmt.Printf("num2的类型是:%T" ,num2) fmt.Println() fmt.Println(unsafe.Sizeof(num2)) var age uint8 = 18 fmt.Println(age) }
字符类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package main import "fmt" func main () { var c1 byte = 'a' fmt.Println(c1) var c2 byte = '6' fmt.Println(c2) var c3 byte = '(' fmt.Println(c3) var c4 int = '中' fmt.Println(c4) var c5 int = 'A' fmt.Printf("c5对应的具体字符为: %c" ,c5) }
转义字符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport "fmt" func main () { fmt.Println("hello\nworld" ) fmt.Println("hello\tworld" ) fmt.Println("hello\bworld" ) fmt.Println("hello\rworld" ) fmt.Println("hello\"world" ) fmt.Println("hello\\world" ) }
字符串类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package mainimport "fmt" func main () { var s1 string = "你好世界" fmt.Println(s1) var s2 string = "hello world" fmt.Println(s2) var s3 string = ` func main() { // \n 换行 fmt.Println("hello\nworld") // \t 制表符 fmt.Println("hello\tworld") // \b 退格 fmt.Println("hello\bworld") // \r 换行 fmt.Println("hello\rworld") // \" 双引号" fmt.Println("hello\"world") // \\ 反斜杠 fmt.Println("hello\\world") } ` fmt.Println(s3) var s5 string = "hello" + "world" s5 += "hello" fmt.Println(s5) }
数据类型默认值 数据类型默认值
整数类型: 0 浮点类型: 0 布尔类型: false 字符串类型: “”
类型转换 (1)Go在不同类型的变量之间赋值需要显式转换
,并且只有在显式转换(强制转换) (2) 语法:
表达式T(v)将值v转换为类型T T:就是数据类型 v:就是需要转换的变量
(3)案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport "fmt" func main () { var n1 int = 10 fmt.Println(n1) var n2 float32 = float32 (n1) fmt.Println(n2) fmt.Printf("%T" , n1) var n3 int32 = 12 var n4 int64 = int64 (n3) + 30 fmt.Println(n4) }
基本数据类型和string类型的转换 (1)在程序开发中,我们经常需要将基本数据类型转换成string类型。或者将string类型转成基本数据类型。 (2)基本类型转换string类型
方式1: ft.Sprintf(“%参数”,表达式) 方式2: 使用strconv包的函数
(3)案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package mainimport fmtfunc main () { var n1 int = 10 var n2 float32 = 12.3 var n3 byte = '中' var s1 string = fmt.Sprintf("%d" , n1) fmt.Println("s1对应的类型是:%T, s1 = %q \n" , s1, s1) var s2 string = fmt.Sprintf("%f" , n2) fmt.Println("s2对应的类型是:%T, s2 = %q \n" , s2, s2) var s3 string = fmt.Sprintf("%f" , n3) fmt.Println("s3对应的类型是:%T, s3 = %q \n" , s3, s3) }
1 2 3 4 5 6 7 8 9 10 11 package mainimport ( "fmt" "strconv" ) func main () { var n1 int = 10 var s1 string = strconv.FormatInt(int64 (n1), 10 ) fmt.Println("s1对应的类型是:%T, s1 = %q \n" , s1, s1) }
指针 总结:指针就是内存地址 &获取内存地址 *从地址里取值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package mainimport fmtfunc main () { var age int = 18 fmt.Println(&age) var ptr *int = &age fmt.Println(ptr) fmt.Println("ptr本身这个存储空间的地址是:" ,ptr) fmt.printf("ptr指向的数值为:%v\n" , *ptr) var num int = 18 fmt.Println(num) var ptrs *int = &num *ptr = 20 fmt.Println(num) }
导入语句 import 导入语句通常放在文件开头包声明语句下。 导入的包名需要使用双引号包裹起来。 包名是从$GOPATH/src/
后开始计算的,使用/进行分隔。
在mac上已经设置好了 $GOPATH ,查看 $GOPATH 输入 go env 即可查看所在路径。 在windows 上需要配置一个环境变量 $GOPATH 指定到对应的工作目录上。
1 2 3 4 5 6 7 8 9 10 11 package mainimport ( "fmt" "test" ) func main () { fmt.Println(test.Nums) }
$GOPATH/src/test/test.go
1 2 3 package testvar Nums int = 99
运算符 +加号 正数,相加操作,字符串拼接
% 取模 两个int 类型运输时,结果也是int类型 如 fmt.Println(10%3) 值 1
/ 除号 两个int 类型运输时,结果也是int类型 如 fmt.Println(10/3) 值 3
浮点类型参与运算,结果为浮点类型 fmt.Println(10.0/3) 值 3.3333333335
获取用户终端输入 在编程中,需要接收用户输入的数据,可以使用标准输入(stdin)来获取用户输入。
1 2 3 4 5 6 //Scanln类似Scan,但在遇到换行符(\n)后立即返回。 func Scanln(a ...interface{}) (n int, err error) //Scanf从标准输入中读取文本,根据fomat参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功读取的参数个数和遇到的错误。 funcScanf(format string, a ...interface{}) (n int, err error)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package mainimport "fmt" func main () { var age int fmt.Println("请输入年龄" ) fmt.Scanln(&age) var name string fmt.Println("请输入姓名" ) fmt.Scanln(&name) var score float32 fmt.Println("请输入成绩" ) fmt.Scanln(&score) var isVip bool fmt.Println("是否是vip" ) fmt.Scanln(&isVip) fmt.Printf("学生的年龄为:%v,姓名为:%v,成绩为:%v,是否是vip为:%v" ,age, name, score, isVip) }
1 2 3 4 5 6 7 8 9 10 11 12 13 package mainimport "fmt" func main () { var age int var name string var score float32 var isVip bool fmt.Println("学生的年龄 ,姓名,成绩,是否是vip, 使用空格进行分割" ) fmt.Scanf("%d %s %f %t" , &age, &name, &score, &isVip) fmt.Printf("学生的年龄为:%v,姓名为:%v,成绩为:%v,是否是vip为:%v" ,age, name, score, isVip) }
流出控制 PS:条件表达式左右到()可以不写 PS: if和表达式中间,一定要有空格 PS: 在Golang中,{} 是必须有的,就算你只写一行代码
注意事项: case 后面的表达式如果是常量值,则要求不能重复 case 后的各个值的数据类型,必须和switch表达式的数据类型一致 case 后面可以带多个值,使用逗号间隔 case 后面不需要带break default语句不是必须,可以任意位置 switch后也可以不带表达式,当if分支来使用 switch后也可以直接声明/定义一个变量,分号结束(不举荐) swicth穿透,利用fallthrough关键字,如果在case语句后增加fallthrough,则会继续执行下一个case,也叫switch穿透
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 package mainimport "fmt" func main () { var count int = 10 if count > 10 { fmt.Println("数量充足!" ) } else if count > 5 && count < 10 { fmt.Println("数量不足10" ) } else { fmt.Println("库存吃紧" ) } if num := 20 ; num > 10 { fmt.Println("数量充足!" ) } var score int = 8 var A int = 10 switch score { case A: fmt.Println("A" ) case 9 ,5 ,6 ,7 : fmt.Println("B" ) case 8 : fmt.Println("C" ) fallthrough default : fmt.Println("D" ) } var sum int for i :=1 ; i <5 ; i++ { sum += i } fmt.Println(sum) q :=1 for q < 5 { fmt.Println("你好" ) q++ } var str string = "hello" for i := 0 ; i < len (str); i++ { fmt.Printf("str[%v]=%v\n" ,i,str[i]) } for i, v := range str { fmt.Printf("str[%v]=%v\n" ,i,v) } }
函数 func 函数名(参数名 参数类型) 返回值类型 { //函数体 }
函数不支持重载 基本数据类型和数组默认都是传递的,即进行值拷贝,在函数内修改,不回影响到原来的值 以值传递方式的数据类型,如果希望在函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量,从效果来看类似引用传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport "fmt" func test (args...int ) { fmt.Println(args) } func demo (num *int ) { *num = 30 } func main () { test (1 ,2 ,3 ,4 ,5 ,6 ,7 ) var num int = 10 fmt.Println(&num) demo(&num) fmt.Println(num) }
函数也是一个数据类型,可赋值给一个变量,则该变量就是一个函数类型的变量。通过该变量可以对函数调用。
函数既然是一种数据类型,因此函数可以作为参数并调用
为来简化数据类型定义,Go支持自定义数据类型,可以通过type关键字定义
支持对函数返回值命名1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 package mainimport "fmt" func test (num int ) { fmt.Println(num) } func test2 (num int , num2 int , testFunc func (int ) ) { fmt.Println("-----test02 \n" ) } type myFunc func (int ) func test3 (num int , num2 int , testFunc myFunc) { fmt.Println("-----test03 \n" ) } func test4 (num int , num2 int ) (int , int ) { result1 := num - num2 result2 := num + num2 return result1, result2 } func test5 (num int , num2 int ) (sum int , sub int ) { sum = num + num2 sub = num - num2 return } func main () { a := test fmt.Printf("a的类型是 %T,test函数的类型是 %T \n" , a, test) a(10 ) test2(2 ,12 ,test) test2(2 ,12 ,a) type myInt int var num1 myInt = 30 fmt.Println(num1) var num2 int = 40 num2 = int (num1) fmt.Println(num2) test3(2 ,12 ,a) b,c := test4(5 ,3 ) fmt.Println(b,c) b,c = test5(4 ,3 ) fmt.Println(b,c) }
init函数
init函数:初始化函数,可以用来进行一些初始化的操作 每一个源文件都可以包含一个init函数,该函数会在main函数之前执行。
全局变量定义,init函数,mian函数的执行流程? 答: 全局变量 –》 init函数 –》 main函数
多个源文件都有init函数的时候,如何执行 答:重上往下,先执行导入所有包的init函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport "fmt" var num int = test()func test () int { fmt.Println("调用了 test函数" ) return 10 } func init () { fmt.Println("调用了 init函数" ) } func main () { fmt.Println("调用了 main函数" ) }