本文共 14606 字,大约阅读时间需要 48 分钟。
【1】Golang 语言简介
【1.1】GO 语言的定义
Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。
【1.2】GO 语言的特点
Go语言既拥有静态编译语言的安全和性能,又拥有动态语言开发维护的高效率;
静态编译语言 : 静态编译语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型;
动态语言 : 动态语言是在运行时确定数据类型的语言,变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型;
【2】Golang 语言基本语法示例
【2.1】变量
golang 中标识符的使用
package mainimport "fmt"//golang 中标识符的使用func main() { //Golang中严格区分大小写 //golang 中 认为 num 和 Num是不同的变量 var num int = 10 var Num int = 20 //输出: num=10 Num=20 fmt.Printf("num=%v Num=%v\n", num, Num) //标识符不能包含空格 //var ab c int = 30 //_ 是空标志符,用于占用 // var _ int = 40 //error // fmt.Println(_) var int int = 90 //输出: 90 fmt.Println(int)}
golang 中变量的使用
package mainimport "fmt"//golang 中变量的使用func main() { //golang的变量使用方式1 //第一种:指定变量类型,声明后若不赋值,使用默认值 // int 的默认值是0 , 其它数据类型的默认值后面马上介绍 var i int //输出: i= 0 fmt.Println("i=", i) //第二种:根据值自行判定变量类型(类型推导) var num = 10.11 //输出: num= 10.11 fmt.Println("num=", num) //第三种:省略var, 注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误 //下面的方式等价 var name string name = "tom" // := 的 :不能省略,否则错误 name := "tom" //输出: name= tom fmt.Println("name=", name)}
package mainimport "fmt"//定义全局变量var n1 = 100var n2 = 200var name = "jack"//上面的声明方式,也可以改成一次性声明var ( n3 = 300 n4 = 900 name2 = "mary")func main() { //该案例演示golang如何一次性声明多个变量 var n5, n6, n7 int //输出: n5= 0 n6= 0 n7= 0 fmt.Println("n5=", n5, "n6=", n6, "n7=", n7) //一次性声明多个变量的方式2 var n8, name3, n9 = 100, "tom", 888 //输出: n8= 100 name3= tom n9= 888 fmt.Println("n8=", n8, "name3=", name3, "n9=", n9) //一次性声明多个变量的方式3, 同样可以使用类型推导 n10, name4, n11 := 100, "tom~", 888 //输出: n10= 100 name4= tom~ n11= 888 fmt.Println("n10=", n10, "name4=", name4, "n11=", n11) //输出全局变量 //输出: n1= 100 name= jack n2= 200 fmt.Println("n1=", n1, "name=", name, "n2=", n2) //输出: n3= 300 name2= mary n4= 900 fmt.Println("n3=", n3, "name2=", name2, "n4=", n4)}
package mainimport ( "fmt" //为了使用utils.go文件的变量或者函数,我们需要先引入该model包 "GO_LEARN_CODE/chapter03/demo04/model")//变量使用的注意事项func main() { //该区域的数据值可以在同一类型范围内不断变化 var i int = 10 i = 30 i = 50 //输出: i= 50 fmt.Println("i=", i) //i = 1.2 //int ,原因是不能改变数据类型 //变量在同一个作用域(在一个函数或者在代码块)内不能重名 //var i int = 59 //i := 99 //我们使用 utils.go 的 heroName 包名.标志符 //输出: 宋江 fmt.Println(model.HeroName)}package model//定义了一个变量var HeroName string = "宋江"
golang 中整数类型使用
package main// import "fmt"// import "unsafe"import ( "fmt" "unsafe")// golang 中整数类型使用func main() { var i int = 1 //输出: i= 1 fmt.Println("i=", i) //测试一下 int8 的范围 -128~127, //其它的 int16, int32, int64, 类推 ... var j int8 = 127 //输出: j= 127 fmt.Println("j=", j) //测试一下 uint8 的范围(0-255),其它的 uint16, uint32, uint64 类推即可 var k uint16 = 255 // 输出: k= 255 fmt.Println("k=", k) //int , uint , rune , byte的使用 var a int = 8900 //输出: a= 8900 fmt.Println("a=", a) var b uint = 1 var c byte = 255 //输出: b= 1 c= 255 fmt.Println("b=", b, "c=", c) //整型的使用细节 var n1 = 100 // n1 是什么类型 //这里我们给介绍一下如何查看某个变量的数据类型 //fmt.Printf() 可以用于做格式化输出。 //输出: n1 的 类型 int fmt.Printf("n1 的 类型 %T \n", n1) //如何在程序查看某个变量的占用字节大小和数据类型 (使用较多) var n2 int64 = 10 //unsafe.Sizeof(n1) 是 unsafe 包的一个函数,可以返回 n1 变量占用的字节数 //输出: n2 的 类型 int64 n2占用的字节数是 8 fmt.Printf("n2 的 类型 %T n2占用的字节数是 %d ", n2, unsafe.Sizeof(n2))}
golang 中小数类型使用
package mainimport ( "fmt" "unsafe")//golang 中小数类型使用func main() { var price float32 = 89.12 //输出: price= 89.12 fmt.Println("price=", price) var num1 float32 = -0.00089 var num2 float64 = -7809656.09 //输出: num1= -0.00089 num2= -7.80965609e+06 fmt.Println("num1=", num1, "num2=", num2) //尾数部分可能丢失,造成精度损失。 -123.0000901 var num3 float32 = -123.0000901 var num4 float64 = -123.0000901 num3= -123.00009 num4= -123.0000901 fmt.Println("num3=", num3, "num4=", num4) //Golang 的浮点型默认声明为 float64 类型 var num5 = 1.1 //输出: num5的数据类型是 float64 fmt.Printf("num5的数据类型是 %T \n", num5) //十进制数形式:如:5.12 .512 (必须有小数点) num6 := 5.12 num7 := .123 //=> 0.123 //输出: num6= 5.12 num7= 0.123 fmt.Println("num6=", num6, "num7=", num7) //科学计数法形式 num8 := 5.1234e2 // 5.1234 * 10的2次方 num9 := 5.1234E2 // 5.1234 * 10的2次方 num10 := 5.1234E-2 // 5.1234 / 10的2次方 0.051234 //输出: num8= 512.34 num9= 512.34 num10= 0.051234 fmt.Println("num8=", num8, "num9=", num9, "num10=", num10) /** * byte 等同于 int8,常用来处理 ascii 字符 * rune 等同于 int32,常用来处理 unicode 或 utf-8 字符 */ var c1 rune = '北' //输出: c1= 21271 4 fmt.Println("c1=", c1, unsafe.Sizeof(c1))}
golang 中基本数据类型的转换
package mainimport ( "fmt")// golang 中基本数据类型的转换func main() { var i int32 = 100 //希望将 i => float var n1 float32 = float32(i) var n2 int8 = int8(i) var n3 int64 = int64(i) //低精度->高精度 //输出: i=100 n1=100 n2=100 n3=100 fmt.Printf("i=%v n1=%v n2=%v n3=%v \n", i, n1, n2, n3) //被转换的是变量存储的数据(即值),变量本身的数据类型并没有变化 //输出: i type is int32 fmt.Printf("i type is %T\n", i) // int32 //在转换中,比如将 int64 转成 int8 【-128---127】 ,编译时不会报错, //只是转换的结果是按溢出处理,和我们希望的结果不一样 var num1 int64 = 999999 var num2 int8 = int8(num1) //输出: num2= 63 fmt.Println("num2=", num2)}
golang 中指针类型使用
package mainimport ( "fmt")//golang 中指针类型func main() { //基本数据类型在内存布局 var i int = 10 // i 的地址是什么,&i //输出: i的地址= 0xc00004e080 fmt.Println("i的地址=", &i) //下面的 var ptr *int = &i //1. ptr 是一个指针变量 //2. ptr 的类型 *int //3. ptr 本身的值&i var ptr *int = &i //输出: ptr=0xc00004e080 fmt.Printf("ptr=%v\n", ptr) //输出: ptr 的地址=0xc000076020ptr 指向的值=10 fmt.Printf("ptr 的地址=%v", &ptr) fmt.Printf("ptr 指向的值=%v", *ptr)}
golang 中字符类型使用
package mainimport ( "fmt")//golang 中字符类型使用func main() { var c1 byte = 'a' var c2 byte = '0' //字符的0 //当我们直接输出byte值,就是输出了的对应的字符的码值 // 'a' ==> //输出: c1= 97 c2= 48 fmt.Println("c1=", c1) fmt.Println("c2=", c2) //如果我们希望输出对应字符,需要使用格式化输出 //输出: c1=a c2=0 fmt.Printf("c1=%c c2=%c\n", c1, c2) //var c3 byte = '北' //overflow溢出 var c3 int = '北' //overflow溢出 //输出: c3=北 c3对应码值=21271 fmt.Printf("c3=%c c3对应码值=%d\n", c3, c3) //可以直接给某个变量赋一个数字,然后按格式化输出时%c,会输出该数字对应的unicode 字符 var c4 int = 22269 // 22269 -> '国' 120->'x' //输出: c4=国 fmt.Printf("c4=%c\n", c4) //字符类型是可以进行运算的,相当于一个整数,运输时是按照码值运行 var n1 = 10 + 'a' // 10 + 97 = 107 //输出: n1= 107 fmt.Println("n1=", n1)}
golang 中 bool 类型使用
package mainimport ( "fmt" "unsafe")//golang 中 bool 类型使用func main() { var b = false //输出: b= false fmt.Println("b=", b) //输出: b 的占用空间 = 1 //注意事项 //1. bool类型占用存储空间是1个字节 fmt.Println("b 的占用空间 =", unsafe.Sizeof(b)) //2. bool类型只能取true或者false}
golang 中 string 类型使用
package mainimport ( "fmt")//golang 中 string 类型使用func main() { //string 的基本使用 var address string = "北京长城 110 hello world!" //输出: 北京长城 110 hello world! fmt.Println(address) //字符串一旦赋值了,字符串就不能修改了:在Go中字符串是不可变的 //var str = "hello" //str[0] = 'a' //这里就不能去修改str的内容,即go中的字符串是不可变的。 //字符串的两种表示形式 //(1) 双引号, 会识别转义字符; //(2) 反引号,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击, 输出源代码等效果 str2 := "abc\nabc" /** * 输出: * abc * abc */ fmt.Println(str2) //使用的反引号 `` str3 := ` package main import ( "fmt" "unsafe" ) //演示golang中bool类型使用 func main() { var b = false fmt.Println("b=", b) //注意事项 //1. bool类型占用存储空间是1个字节 fmt.Println("b 的占用空间 =", unsafe.Sizeof(b) ) //2. bool类型只能取true或者false } ` fmt.Println(str3) //字符串拼接方式 var str = "hello " + "world" str += " haha!" fmt.Println(str) //当一个拼接的操作很长时,怎么办,可以分行写,但是注意,需要将+保留在上一行. str4 := "hello " + "world" + "hello " + "world" + "hello " + "world" + "hello " + "world" + "hello " + "world" + "hello " + "world" fmt.Println(str4) var a int // 0 var b float32 // 0 var c float64 // 0 var isMarried bool // false var name string // "" //这里的 %v 表示按照变量的值输出 //输出: a=0,b=0,c=0,isMarried=false name= fmt.Printf("a=%d,b=%v,c=%v,isMarried=%v name=%v", a, b, c, isMarried, name)}
golang 中基本数据转成 string
package mainimport ( "fmt" "strconv" _ "unsafe")//golang 中基本数据转成 stringfunc main() { var num1 int = 99 var num2 float64 = 23.456 var b bool = true var myChar byte = 'h' var str string //空的str //使用第一种方式来转换 fmt.Sprintf 方法 //输出: str type string str="99" str = fmt.Sprintf("%d", num1) fmt.Printf("str type %T str=%q\n", str, str) //输出: str type string str="23.456000" str = fmt.Sprintf("%f", num2) fmt.Printf("str type %T str=%q\n", str, str) //输出: str type string str="true" str = fmt.Sprintf("%t", b) fmt.Printf("str type %T str=%q\n", str, str) //输出: str type string str="h" str = fmt.Sprintf("%c", myChar) fmt.Printf("str type %T str=%q\n", str, str) //第二种方式 strconv 函数 var num3 int = 99 var num4 float64 = 23.456 var b2 bool = true //输出: str type string str="99" str = strconv.FormatInt(int64(num3), 10) fmt.Printf("str type %T str=%q\n", str, str) // strconv.FormatFloat(num4, 'f', 10, 64) // 说明: 'f' 格式 10:表示小数位保留10位 64 :表示这个小数是 float64 // 输出: str type string str="23.4560000000" str = strconv.FormatFloat(num4, 'f', 10, 64) fmt.Printf("str type %T str=%q\n", str, str) //输出: str type string str="true" str = strconv.FormatBool(b2) fmt.Printf("str type %T str=%q\n", str, str) //strconv 包中有一个函数 Itoa //输出: str type string str="4567" var num5 int64 = 4567 str = strconv.Itoa(int(num5)) fmt.Printf("str type %T str=%q\n", str, str)}
golang 中 string 转成基本数据类型
package mainimport ( "fmt" "strconv")// golang 中 string 转成基本数据类型func main() { // 输出: b type bool b=true var str string = "true" var b bool // b, _ = strconv.ParseBool(str) // 说明 // 1. strconv.ParseBool(str) 函数会返回两个值 (value bool, err error) // 2. 因为我只想获取到 value bool ,不想获取 err 所以我使用_忽略 b, _ = strconv.ParseBool(str) //输出: b type bool b=true fmt.Printf("b type %T b=%v\n", b, b) // 输出: n1 type int64 n1=1234590 // n2 type int n2=1234590 var str2 string = "1234590" var n1 int64 var n2 int n1, _ = strconv.ParseInt(str2, 10, 64) n2 = int(n1) //输出: n1 type int64 n1=1234590 fmt.Printf("n1 type %T n1=%v\n", n1, n1) //输出: n2 type int n2=1234590 fmt.Printf("n2 type %T n2=%v\n", n2, n2) // 输出: f1 type float64 f1=123.456 var str3 string = "123.456" var f1 float64 f1, _ = strconv.ParseFloat(str3, 64) //输出: f1 type float64 f1=123.456 fmt.Printf("f1 type %T f1=%v\n", f1, f1) // 输出: n3 type int64 n3=0 var str4 string = "hello" var n3 int64 = 11 n3, _ = strconv.ParseInt(str4, 10, 64) //输出: n3 type int64 n3=0 fmt.Printf("n3 type %T n3=%v\n", n3, n3)}
【2.2】运算符
golang 语言运算符注意点总结
++,-- 运算符
package mainimport ( "fmt" _ "fmt")func main() { //在golang中,++ 和 -- 只能独立使用. var i int = 8 // var a int // a = i++ //错误,i++只能独立使用 // a = i-- //错误, i--只能独立使用 // 编译出错 // if i++ > 0 { // fmt.Println("ok") // } i++ // ++i // 错误,在golang没有 前++ fmt.Println("i=", i) i-- // --i // 错误,在golang没有 前-- fmt.Println("i=", i)}
【2.3】典型流程控制示例
golang 语言 break 总结
package mainimport ( "fmt" "math/rand" "time")func main() { //我们为了生成一个随机数,还需要个rand设置一个种子. //time.Now().Unix() : 返回一个从1970:01:01 的0时0分0秒到现在的秒数 //rand.Seed(time.Now().Unix()) //如何随机的生成1-100整数 //n := rand.Intn(100) + 1 // [0 100) //fmt.Println(n) //随机生成1-100的一个数,直到生成了99这个数,看看你一共用了几次 //分析思路: //编写一个无限循环的控制,然后不停的随机生成数,当生成了99时,就退出这个无限循环==》break var count int = 0 for { rand.Seed(time.Now().UnixNano()) n := rand.Intn(100) + 1 fmt.Println("n=", n) count++ if n == 99 { break //表示跳出for循环 } } fmt.Println("生成 99 一共使用了 ", count) //这里演示一下指定标签的形式来使用 break //break 语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块 //lable2: for i := 0; i < 4; i++ { lable1: // 设置一个标签 for j := 0; j < 10; j++ { if j == 2 { // break // break 默认会跳出最近的for循环 break lable1 // break lable2 } //break : j=0,j=1; i=0,i=1,i=2,i=3; //break lable1 : j=0,j=1; i=0,i=1,i=2,i=3; //break lable2 : j=0,j=1; i 不会打印; fmt.Println("j=", j) } fmt.Println("i=", i) }}
golang 语言 continue 总结
package mainimport "fmt"func main() { //continue案例 //这里演示一下指定标签的形式来使用lable2: for i := 0; i < 4; i++ { // lable1: // 设置一个标签 for j := 0; j < 10; j++ { if j == 2 { // continue // continue lable1 continue lable2 } // continue : i=0--3;j=0,1,3--9; // continue lable1 : i=0--3;j=0,1,3--9; // continue lable2 : j=0,1; i 不打印 fmt.Println("j=", j) } fmt.Println("i=", i) }}
golang 语言 for 总结
package mainimport ( "fmt")func main() { //for 循环的第一种写法 for i := 1; i <= 10; i++ { fmt.Println("你好,尚硅谷", i) } //for 循环的第二种写法 j := 1 //循环变量初始化 for j <= 10 { //循环条件 fmt.Println("你好,尚硅谷~", j) j++ //循环变量迭代 } //for 循环的第三种写法, 这种写法通常会配合 break 使用 k := 1 for { // 这里也等价 for ; ; { if k <= 10 { fmt.Println("ok~~", k) } else { break //break就是跳出这个for循环 } k++ } //字符串遍历方式1-传统方式 var str string = "hello,world!北京" for i := 0; i < len(str); i++ { fmt.Printf("%c \n", str[i]) //使用到下标... } //字符串遍历方式1-传统方式 str2 := []rune(str) // 就是把 str 转成 []rune for i := 0; i < len(str2); i++ { fmt.Printf("%c \n", str2[i]) //使用到下标... } //字符串遍历方式2-for-range str = "abc~ok上海" for index, val := range str { fmt.Printf("index=%d, val=%c \n", index, val) }}
golang 语言 goto / return 总结
package mainimport ( "fmt")func main() { var n int = 30 //演示goto的使用 fmt.Println("GOTO1") if n > 20 { goto label1 } fmt.Println("GOTO2") fmt.Println("GOTO3") fmt.Println("GOTO4")label1: fmt.Println("GOTO5") fmt.Println("GOTO6") fmt.Println("GOTO7") //演示return的使用 fmt.Println("RETURN1") if n > 20 { return } fmt.Println("RETURN2") fmt.Println("RETURN3") fmt.Println("RETURN4") fmt.Println("RETURN5") fmt.Println("RETURN6") fmt.Println("RETURN7")}
golang 语言 switch 总结
package mainimport ( "fmt")func main() { //go 语言中 switch 匹配后不需要加 break 自动退出 var n1 int32 = 51 var n2 int32 = 20 switch n1 { case n2, 10, 5: // case 后面可以有多个表达式 fmt.Println("ok1") case 90: fmt.Println("ok2~") } //switch 后也可以不带表达式,类似 if--else 分支来使用。【案例演示】 var age int = 10 switch { case age == 10: fmt.Println("age == 10") case age == 20: fmt.Println("age == 20") default: fmt.Println("没有匹配到") } //case 中也可以对 范围进行判断 var score int = 90 switch { case score > 90: fmt.Println("成绩优秀..") case score >= 70 && score <= 90: fmt.Println("成绩优良...") case score >= 60 && score < 70: fmt.Println("成绩及格...") default: fmt.Println("不及格") } //switch 后也可以直接声明/定义一个变量,分号结束,不推荐 switch grade := 90; { // 在golang中,可以这样写 case grade > 90: fmt.Println("成绩优秀~..") case grade >= 70 && grade <= 90: fmt.Println("成绩优良~...") case grade >= 60 && grade < 70: fmt.Println("成绩及格~...") default: fmt.Println("不及格~") } //switch 的穿透 fallthrought //在 case 语句块后添加 fallthrought 则会继续执行下一个 case var num int = 10 switch num { case 10: fmt.Println("ok1") fallthrough //默认只能穿透一层 case 20: fmt.Println("ok2") fallthrough case 30: fmt.Println("ok3") default: fmt.Println("没有匹配到..") }}
golang 语言 while 总结
package mainimport "fmt"func main() { //使用while方式输出10句 "hello,world" //循环变量初始化 var i int = 1 for { if i > 10 { //循环条件 break // 跳出for循环,结束for循环 } fmt.Println("hello,world", i) i++ //循环变量的迭代 } fmt.Println("i=", i) //使用的do...while实现完成输出10句”hello,ok“ var j int = 1 for { fmt.Println("hello,ok", j) j++ //循环变量的迭代 if j > 10 { break //break 就是跳出for循环 } }}
参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。
【1】尚硅谷_韩顺平_Go语言核心编程
【2】
【3】
转载地址:http://ismr.baihongyu.com/