1. Go的学习方法
- 高效而愉快的学习
- 先建立一个整体框架,然后细节
- 在实际工作中,要培养用到什么,能够快速学习什么能力
- 先know how,再know why
- 编程软件是一门“做中学”的学科,不是会了再做,而是做了才会
- 适当的囫囵吞枣
- 学习软件编程是在琢磨别人怎么做,而不是我认为应该怎么做的过程
2. 学习新的技术或者知识点
- 原理
- 基础语法
3. 快速入门案例:
- 一个简单的案例
- 了解技术或者知识点的基本使用
细节:
- 怎么使用更规范
- 使用陷阱
- 需要使用时,注意点
demo
package main//把这个 归属到main
import "fmt"//引入一个包fmt
func main(){
//输出hello
("hello")
}
安装相关
C:\Users\care>cd D:\go\bin
D:\go\bin>go version
go version go1.12.5 windows/amd64
但是移到其他位置
D:\go>go version
'go' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
需要配置环境变量:在环境变量中
GOPATH
D:\goproject
GOROOT
D:\go
path
D:\go\bin
再次测试:go version
第一个demo:
package main
import "fmt"
func main(){
("hello world")
}
正确
package main
import "fmt"
func main() {
("Hello, World!")
}
问题:
在go build编译后,如果无报错会生成一个文件
D:\goproject\src\go_code\project01\main>go build
D:\goproject\src\go_code\project01\main>
hello, world
D:\goproject\src\go_code\project01\main>go run
hello, world
4. Golong流程分析
- 源码编译
.go文件
通过go build
编译成.exe
可执行文件,再运行得到结果 - go run
.go文件
通过go run
编译运行一步得到结果
编译成可执行文件,在非go环境下也可以执行。
5. Golang程序开发注意事项
- 源文件以"go"为扩展名
- 严格区分大小写
- 一条条语句过程,不需要分号,不能并列写
- Go 编译器是一行行进行编译的
- go 语言定义的变量或者 import 的包如果没有使用到,代码不能编译通过
- 大括号都是成对出现的,缺一不可
6. Go语言的转义字符(escape char)
-
\t
表示一个制表符 -
\n
换行符 -
\\
一个\ -
\"
一个” -
\r
回车
实例:
package main
import "fmt"
func main(){
("张森森\t没有什么能够打倒你,除非你不想赢")
("张森森\n没有什么能够打倒你,除非你不想赢")
("张森森\\没有什么能够打倒你,除非你不想赢")
("张森森\"没有什么能够打倒你,除非你不想赢")
("张森森,没有什么能够打倒你,除非你不想\r北木")
}
效果
D:\goproject\src\go_code\project01\main>go run
张森森 没有什么能够打倒你,除非你不想赢
张森森
没有什么能够打倒你,除非你不想赢
张森森\没有什么能够打倒你,除非你不想赢
张森森"没有什么能够打倒你,除非你不想赢
北木森,没有什么能够打倒你,除非你不想
作业
D:\goproject\src\go_code\project01\main>go run
姓名 年龄 籍贯 住址
john 12 河北 北京
代码
package main
import "fmt"
func main(){
("姓名\t年龄\t籍贯\t住址\njohn\t12\t河北\t北京")
}
7. 注释
- 行注释
- 块注释
块注释不能嵌套
8. 代码规范
- 官方推荐行注释
- 正确的缩进(一个tab),shif+tab全体左移再tab
- gofmt格式化(gofmt 演示,gofmt -w 写入)
- 运算符两边习惯性加空格(
var num = 2 + 3 * 5
) - 函数大括号必须在小括号后面
- 一行最长不超过80个字符,超过换行
举例:
```
package main
import "fmt"
func main() {
// ("张三\t没有什么能够打倒你,除非你不想赢")
// ("张三\n没有什么能够打倒你,除非你不想赢")
// ("张三\\没有什么能够打倒你,除非你不想赢")
// ("张三\"没有什么能够打倒你,除非你不想赢")
// ("张三,没有什么能够打倒你,除非你不想\r北木")
// var num = 2 + 3*5
("张三,没有什么能够打倒你,没有什么能够打倒你,没有什么能够",
"打倒你,没有什么能够打倒你,没有什么能够打倒你,没有什么能够打倒你,没有什么",
"能够打倒你,没有什么能够打倒你,没有什么能够打倒你,没有什么能够打倒你,没有什",
"么能够打倒你,除非你不想\r北木")
}
```
9. dos基本操作
1. 目录操作
- 查看当前目录
D:\>dir
- 切换到D盘:
C:\Users\care>d:
- 相对路径:
d:\goproject>cd src
- 绝对路径:
C:\Users\care>cd D:\goproject>src
- 切换到上一级
d:\goproject\src>cd ..
- 切换到根目录
cd \
- 新建目录
d:\goproject>md test01
- 新建多个目录
d:\goproject>md test04 test05
- 删除空目录
rd test01
- 删除目录及下面的子目录和文件(不带询问)
d:\goproject>rd /q/s test01
- 删除目录及下面的子目录和文件(带询问)
d:\goproject>rd /s test01
2. 文件的操作
-
新建或追加内容到文件
d:\goproject>echo hello > d:\goproject\test01\
-
复制或者移动文件
复制d:\goproject\test01>copy d:\goproject\test02
复制重命名
d:\goproject\test01>copy d:\goproject\test03\
-
移动
d:\goproject\test01>move f:\
-
删除文件
- 删除指定文件
d:\goproject\test02>del
- 删除所有文件
d:\goproject\test03>del *.text
- 删除指定文件
-
清屏
cls
-
退出
exit
-
新建文件
cd.>
10. 变量
package main
import "fmt"
func main(){
var i int//不赋值默认是0
fmt.Println("i=",i)
var n = 10//(可以忽略类型)
fmt.Println("n=",n)
g := "cate"//等价var g string g = “cate”
fmt.Println("g=",g)
}
注意事项:
- 默认赋值是0
- 先定义后赋值
- 省略
var
,用:=
,已经声明过的变量不能再重新声明 - 多变量声明
package main
import "fmt"
func main(){
var i int//不赋值默认是0
fmt.Println("i=",i)
var n = 10
fmt.Println("n=",n)
g := "cate"//等价var g string g = “cate”
fmt.Println("g=",g)
var n1, n2, n3 int//多变量声明1
var name, age, sex = "care",18,"男"//多变量声明2
a1,a2,a3 := 1,2,"care"//多变量声明3
fmt.Println("n1=",n1, "n2=",n2,"n3=",n3);
fmt.Println("name=",name, "age=",age,"sex=",sex);
fmt.Println("a1=",a1, "a2=",a2,"a3=",a3);
}
全局变量:在函数外部的变量
两种方式:
package main
import "fmt"
// var a1 = 1
// var a2 = "care"
// var a3 = 12
var (
a1 = 2
a2 = "pony"
a3 = 12
)
func main(){
fmt.Println("a1=",a1,"a2=",a2,"a3=",a3)
}
- 该区域的数据值可以在同一类型范围内不断变化
package main
import "fmt"
func main(){
i := 1
//var i int = 1
i := 1.1//报错
fmt.Println("i=",i)
}
- 变量在同一个作用域(函数内)不能重名
package main
import "fmt"
func main(){
var i int = 1
// i := 1
// i := 1.1//报错
fmt.Println("i=",i)
i := 12//错误
var i int = 12//错误
}
- 变量三要素:变量名+值+数据类型
- Golang变量没有赋值的话,int默认为0,小数默认为0,string默认为空字符串
11. 程序中 + 号的使用
- 左右两边都是字符串,+号是拼接
- 左右两边都是数值型,+号是加法运算
package main
import "fmt"
func main(){
// var a = 1;
// var b = 2;
// var c = a + b //3
var a = "1";
var b = "2";
var c = a + b
fmt.Println("c=",c)//12
}
12. 数据类型的基本介绍
8位一个字节,int8,一个字节
整数
说明: int8 :8位,第一位表示正负,0是正,1是负。所以正数2的7次方-1
var n int8 = -129
fmt.Println("n=",n)
报错constant -129 overflows int8
说明:全是0,表示0,全是1,2的8次方,减去全是0,255(0~2的8次方-1)
13. 整型的使用细节
- Golong的各整数类型分为:有符号和无符号,int和uint的大小和系统有关。
- 整型默认声明为int
- 如何在程序中查看某个变量的字节大小和数据类型
- 整型变量在使用时,遵守保小不保大的原则。(保证程序正常运行下,尽量使用空间小的类型 var age byte = 8)
- bit,计算机中最小的存储单位,byte,计算机中基本存储单元。1byte=8bit 8位一个字节
// import "fmt"
// import "unsafe"
import (
"fmt"
"unsafe"
)
//查看类型 默认是int
var n = 100;
fmt.Printf("n的类型%T",n) //n的类型int
//如何在程序中查看某个变量的字节大小和数据类型
var a = 10
// 是 unsafe包的一个函数,可以返回n1变量占用的字节数(import “unsafe”)
fmt.Printf("a的类型%T a占用的字节数是 %d",a,unsafe.Sizeof(a))
14. 小数类型(浮点型)
1、基本介绍:
小数类型就是用于存放小数
2、浮点型的分类
说明:
1. 浮点数在机器中存放形式:浮点数=符号位+指数位+尾数位(浮点数都是有符号的)
- 尾数部分可能丢失,造成精度丢失
var num1 float32 = -123.0000901
var num2 float64 = -123.0000901
fmt.Println("num1= ",num1, "num2= ",num2)
//num1= -123.00009 num2= -123.0000901
浮点型使用细节:
-
Golong中的浮点型有固定的范围和字段长度,不受具体OS(操作系统)的影响
-
Golong中浮点型默认声明是float64,float64精度比float32高
-
浮点型常量有两种表现形式
-
十进制形式 5.12 、0.512(可缩写陈
.512
,必须有小数点) -
科学计数法形式:
5.1234e2 = 5.12*10的2次方,
5.1234E2 = 5.12*10的2次方,
5.12E-2=5.12/10的2次方,
-
-
通常情况下应该使用float64位,精度高
num3 := 5.1234e2
num4 := 5.1234E2
num5 := 5.1234e-2
fmt.Println("num3= ",num3, "num4= ",num4,"num5= ",num5)
//num1= 512.34 num2= 512.34 num5= 0.051234
15. 字符类型
1、基本介绍
Golang中没有专门的字符类型,如果要存储单个字符(字母),一般使用byte来保存
字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的,他就是说对于传统的字符串是由字符组成的,而go的字符串不同,它是由字节组成的。
2、案例演示
package main
import "fmt"
func main(){
var c1 byte = 'a'
var c2 byte = '0'//字符的0
//但我们直接输出byte值,就是输出它对应的字符的码值
fmt.Println("c1=",c1)//97
fmt.Println("c2=",c2)//48
//如果我们希望输出对应字符,需要使用格式化输出
fmt.Printf("c1=%c c2=%c",c1 ,c2)
// var c3 byte = "北"//cannot use "北" (type string) as type byte in assignment
var c3 int = '北'
fmt.Printf("c3=%c c3对应码值%d",c3,c3)
}
注意赋值的时候,是单引号,格式化字符是%c,类型是%t,数字是%d
- 如果我们保存的字符在 ASCII 表的,比如[0-1, a-z,A-Z…]直接可以保存到 byte
- 如果我们保存的字符对应码值大于 255,这时我们可以考虑使用 int 类型保存
- 如果我们需要安装字符的方式输出,这时我们需要格式化输出,即 (“%c”, c1)
16. 字符类型使用细节
- 字符常量是用单引号(’’)括起来的单个字符
- Go 中允许使用转义字符 '\’来将其后的字符转变为特殊字符型常量。例如:var c3 char = ‘\n’ // '\n’表示换行符
- Go语言的字符使用UTF-8编码,如果想查询字符对应的utf8码值
/classcode/tools/encode_utf8.asp
英文字母-1 个字节 汉字-3 个字节
- 在 Go 中,字符的本质是一个整数,直接输出时,是该字符对应的 UTF-8 编码的码值。
- 可以直接给某个变量赋一个数字,然后按格式化输出时%c,会输出该数字对应的 unicode 字符
- 字符类型是可以进行运算的,相当于一个整数,因为它都对应有Unicode 码
.
//字符可以运算,直接赋值某个变量一个数字,然后格式化输出会输出该数字对应的Unicode码值
var c4 int = 22269
fmt.Printf("c4=%c\n",c4)//国
var n1 = 10 +'a'//10+97 = 107
fmt.Println("n1=",n1)//48
17. 字符类型本质探讨
- 字符型 存储到 计算机中,需要将字符对应的码值(整数)找出来存储:字符—>对应码值---->二进制–>存储
读取:二进制----> 码值 ----> 字符 --> 读取
- 字符和码值的对应关系是通过字符编码表决定的(是规定好)
- Go 语言的编码都统一成了 utf-8。非常的方便,很统一,再也没有编码乱码的困扰了
18. 布尔类型
- 布尔类型,bool,只允许取值:true和false(不可以是0或者非0)
- bool类型占一个字节
- 逻辑运算,一般用于程序流程控制
19. 字符串类型
字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用UTF-8 编码标识Unicode 文本
package main
import "fmt"
func main(){
var address string = "北京欢迎你 hello go 123"
var address string = 'sads北京是你的'
//.\:5:6: cannot use '\u0000' (type rune) as type string in assignment
//.\:5:23: invalid character literal (more than one character)
var name = `\n func`//反引号
fmt.Println(address);
//字符串拼接
var str = "hello" + "world"
str += "go"
fmt.Println(str)
}
注意细节
- golang中的字符串是不可变的
- 必须用双引号,双引号会转义字符
- 反引号,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击、输出源代码等效果
- 字符串拼接
- 多个加号的话,换行需要把+号放在最后,这样go运算时,如最后没有运算符默认是分号
基本数据类型的默认值
整型 0
浮点型 0
字符串 “”
布尔类型 false
var a int
var b float32
var c float64
var isMale bool
var name string
//%v 按照变量的原值输出 ("a=%d,b=%f,c=%f,isMale=%v,name=%v",a,b,c,isMale,name)
20. 基本数据类型的转换
1、基本介绍
Golang 和 java / c 不同,Go 在不同类型的变量之间赋值时需要显式转换。也就是说 Golang 中数据类型不能自动转换。
2、基本语法
package main
import "fmt"
func main(){
var i int32 = 100
var n1 float32 = float32(i)
var n2 int8 = int8(i)
var n3 int64 = int64(i)
fmt.Printf("i=%v n1=%v n2=%v n3=%v",i ,n1, n2 ,n3 )
}
//i=100 n1=100 n2=100 n3=100
var num1 int64 = 999999
var num2 int8 = int8(num1)
fmt.Println("num2=",num2)
//num2 = 63 被溢出处理
注意事项
- 数据类型的转换可以是从
表示范围小–>表示范围大,也可以 范围大—>范围小 - 被转换的是变量存储的数据(即值),变量本身的数据类型并没有变化!
- 在转换中,比如将 int64 转成 int8 【-128—127】 ,编译时不会报错,只是转换的结果是按溢出处理,和我们希望的结果不一样。 因此在转换时,需要考虑范围.
var n1 int32 =12
var n2 int64
var n3 int8
n2 = n1 + 20
n3 = n1 + 20
//.\:16:5: cannot use n1 + 20 (type int32) as type int64 in assignment
//.\:17:5: cannot use n1 + 20 (type int32) as type int8 in assignment
n2 = int64(n1) + 20
n3 = int8(n1) + 20
var n1 int32 =12
var n2 int8
// var n3 int8
n2 = int8(n1) + 127//编译通过,但是结果不是139,被溢出处理 -117
// n3 = int8(n1) + 128//编译不通过 constant 128 overflows int8
fmt.Println(n2)
21. 基本数据类型和string的转换
1、基本数据类型转string
- 方式一、("%参数",表达式)
- 方式二、使用strconv包的行数
var num1 int = 99
var num2 float64 = 23.456
var b bool = true
var myChar byte = 'h'
var str string
str = fmt.Sprintf("%d",num1);
fmt.Printf("str type %T str=%v\n",str ,str) //str type string str=99
str = fmt.Sprintf("%f",num2);
fmt.Printf("str type %T str=%v\n",str ,str)//str type string str=23.456000
str = fmt.Sprintf("%t",b);
fmt.Printf("str type %T str=%v\n",str ,str)//str type string str=true
fmt.Printf("str type %T str=%q\n",str ,str)//str type string str="true"
str = fmt.Sprintf("%c",myChar);
fmt.Printf("str type %T str=%q\n",str ,str)
//str type string str=99
//str type string str=23.456000
//str type string str=true
//str type string str="true"
//str type string str="h"
第二种方式转:
var num3 int = 99
var num4 float64 = 23.456
var b2 bool = true
var str string
str = strconv.FormatInt(int64(num3),10)
fmt.Printf("str type %T str=%q\n",str,str)
//说明:“f”格式 10:保留10位小数,64:float64
str = strconv.FormatFloat(num4,'f',10,64)
fmt.Printf("str type %T str=%q\n",str ,str)
str = strconv.FormatBool(b2)
fmt.Printf("str type %T str=%q\n",str ,str)
//strconv包中有一个函数Itoa
var num5 = 4567
str = strconv.Itoa(num5)
fmt.Printf("str type %T str=%q\n",str,str)
var num6 int64 = 4567
str = strconv.Itoa(int(num6))
fmt.Printf("str type %T str=%q\n",str,str)
//str type string str="99"
//str type string str="23.4560000000"
//str type string str="true"
//str type string str="4567"
2、string转基本数据类型
var str string = "true"
var b bool
// b, _ = (str)
// 说明
// 1. (str) 函数会返回两个值 (value bool, err error)
// 2. 因为我只想获取到 value bool ,不想获取 err 所以我使用_忽略
b , _ = strconv.ParseBool(str)
fmt.Printf("b type %T b=%v\n", b, b)
var str2 string = "1234590"
var n1 int64
var n2 int
n1, _ = strconv.ParseInt(str2, 10, 64)
n2 = int(n1)
fmt.Printf("n1 type %T n1=%v\n", n1, n1)
fmt.Printf("n2 type %T n2=%v\n", n2, n2)
var str3 string = "123.456"
var f1 float64
f1, _ = strconv.ParseFloat(str3, 64)
fmt.Printf("f1 type %T f1=%v\n", f1, f1)
//注意:
var str4 string = "hello"
var n3 int64 = 11
n3, _ = strconv.ParseInt(str4, 10, 64)
fmt.Printf("n3 type %T n3=%v\n", n3, n3)
b type bool b=true
n1 type int64 n1=1234590
n2 type int n2=1234590
f1 type float64 f1=123.456
n3 type int64 n3=0
说明:如果把字符串“hello”强制转成int,会返回默认值0,float成0,bool成false