一、package
package时最基本的分发单位和工程管理中依赖关系的体现;
每个Go语言源代码文件开都都有一个package的声明,表示源码文件所属于代码包;
要生成GO语言可执行程序,必须要有main的package包,且必须在该包下有main函数;
同一个路径下只能存在一个package,一个package可以由多个源文件组成
二、import
总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
import 只有一个功能,导入源代码依赖的package包,需要注意一下点:
不能导入源代码未用到的package包,否则go语言编译器会报错;
如果一个main包带入其它多个包,包将被顺序导入
如果main包中导入的包(如A包)中又依赖了其它的包(如B包),会首先导入依赖的B包,然后初始化B包中的常量和变量,如果B包中还有init函数,会自动执行init函数,当main包中的所有包导入完后,才会对main包中的常量和变量进行初始化,然后执行main包中的init函数,最后执行main包中的main函数;
如果一个包被导入多次,则该包只被导入依次;
import 有如下两种写法总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
方式一:
import "package1"import "package2"import "package3"……
总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
方式二:
import("package1""package2""package3"……)
总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
import 还有以下常用用法:
1、别名操作:将导入的包命名为另一个容易记忆的别名;
package mainimport (mypackage "fmt")func main() {mypackage.Println("Hello World")}
总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
2、点(.)操作:通过点标识导入包后,调用该包中的函数时可以省略包前缀;
package mainimport (. "fmt")func main() {Println("Hello World")}
总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
3、下划线(_)操作:用下划线导入的包,不导入整个包,而是执行包中的init函数,无法通过包名来调用包中的其他函数。使用下划线操作往往是为了注册包中的引擎,让外部方便调用。
package mainimport (_ "fmt")func main() {fmt.Println("Hello World")
运行程序,报错,表示fmt未定义
# command-line-arguments.\HelloWorld.go:7:2: undefined: fmt12
三、数据类型总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
基本数据类型包括数值型、布尔型、字符串型。
总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
变量被声明后的默认值情况:值类型的默认值为0,布尔型的默认值为false,String类型的默认值为空。
1、数组类型
一个数组只能容纳若干相同类型的元素。
var arry1 [3]int //声明一个int类型的数组arry1[0] = 0arry1[1] = 1arry1[2] = 2var arry2 = [3]string{"a", "b", "c"} //声明并定义数组类型var arry3 = [...]int{4, 5, 6} //声明定义时,没有指定长度var num int = len(arry3) //求数组的长度
2、切片类型
切片类型与数组类型类似,可以容纳若干数据类型相同的元素,但切片类型不是定长度,切片类型可以通过数组进行切取
var arry1 = [6]int{1, 2, 3, 4, 5, 6}var slice1 = arry1[1:3]fmt.Println(len(slice1)) //2fmt.Println(slice1) //[2 3]var slice2 = arry1[1:4:6]fmt.Println(len(slice2)) //3fmt.Println(slice2) //[2 3 4]var slice3 = append(slice2, 5, 6, 7)fmt.Println(len(slice3)) //6fmt.Println(slice3) //[2 3 4 5 6 7]var slice4 = []int{0, 0, 0, 0, 0, 0}copy(slice4, slice2)fmt.Println(len(slice4)) //6fmt.Println(slice4) //[2 3 4 0 0 0]
3、字典类型
字典类型用于存储键值对,同一个字典中的每个键都是唯一的。如果我们在向字典中放入一个键值对的时候其中已经有相同的键的话,那么与此键关联的那个值会被新值替换。
/*int键类型,string表示值类型*/map1 := map[int]string{1:"a", 2:"b", 3:"c", 4:"d", 6:"f"}/*6为键*/value1 := map1[6]fmt.Println(value1) //fmap1[5] = "e"value5, ok := map1[5]fmt.Println(value5) //efmt.Println(ok) //true/*删除键*/delete(map1, 6)fmt.Println(map1) //map[1:a 2:b 3:c 4:d 5:e]
4、函数类型
go语言中函数由func关键字表示,在go语言中可以把函数赋给一个变量,通过变量来调用函数,例如 type myFunc my_func(s1 string, s2 string) string。常用形式如下:
package mainimport "fmt"func myfun(s1 string, s2 string) string { return s1 + s2}func myfun1(s1 string, s2 string) (result string) { result = s1 + s2 return result}func myfun2(s1 string, s2 string) (int, string) { result := s1 + s2 num := len(result) return num, result}func main() { s := myfun("hello ", "world") fmt.Println(s) //hello world s1 := myfun1("hello ", "china") fmt.Println(s1) //hello china num, s2 := myfun2("hello ", "lzj") fmt.Println(num) //9 fmt.Println(s2) //hello lzj}
5、指针
go语言中指针表示形式与C语言中的类似,都是通过"*“获取地址中的值,通过”&"获取地址,用法如下:
用法一(同C写法):
package mainimport "fmt"type Person struct { name string age int}func increaseAge(num int, person *Person) { (*person).age = (*person).age + num}func increaseAge2(num int, person Person) { person.age = person.age + num}func main() { var p1 *Person var p2 Person p1 = &Person{"lzj", 25} /*p1是一个指针,下面把该指针的副本传递给了increaseAge函数, p1的副本与p1同指向一个内存位置,所以p1的副本在increaseAge方法中修改了值, 那么p1中的值也被修改了 */ increaseAge(3, p1) //方法中改变了p1的值 fmt.Println((*p1).age) //28 /*p2是非指针类型的变量,下面把p2的值得副本传递给了increaseAge2函数 p2的副本值改变了,但不影响p2的值,因为p2的副本仅是p2值得一个copy */ p2 = Person{"Bob", 20} increaseAge2(5, p2) //方法未改变p2的值 fmt.Println(p2.age) //25}
用法二:总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
package mainimport "fmt"type Person2 struct { name string age int}/*接受者类型是指针,称该方法为指针方法*/func (person *Person2) increaseAge(num int){ /*也可以写成person.age,会自动把person理解为指针的*/ (*person).age = (*person).age + num}/*接受者类型为原型,称该方法为值方法*/func (person Person2) increaseAge2(num int){ person.age = person.age + num}func main() { var p1 *Person2 p1 = &Person2{"lzj", 25} p1.increaseAge(3) fmt.Println((*p1).age) var p2 Person2 p2 = Person2{"Bob", 20} p2.increaseAge2(3) fmt.Println(p2.age)}
6、interface总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
interface时一种类型,时拥有一组方法的类型,用type来定义。如果一个类型实现了interface中的所有方法,那么该类型是interface的一个实现类。interface类型可以没有方法,是一个empty interface,任何类型都是empty interface的实现类。
package mainimport "fmt"type I interface { Get() int Set(int)}type S struct { Age int}func(s S) Get()int { return s.Age}func(s *S) Set(age int) { s.Age = age}func f(i I){ i.Set(10) fmt.Println(i.Get()) //输出10}func main() { s := S{} f(&s)}
7、struct类型总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
Go语言中struct类型与C类似,但比C中的更灵活,可以为struct类型实现新的方法。
package mainimport "fmt"type Student struct { name string age int}/*可以为student类型添加方法*/func (student *Student) increaseAge(num int) { (*student).age = (*student).age + num}func main() { /*创建一个Student类型的值时,可以按顺序写,省略内部字段名*/ student := Student{"lzj", 25} (&student).increaseAge(3) fmt.Println(student.age) //28 /*创建一个Student类型的值时,也可以选择不省略字段名*/ student2 := Student{name:"Bob", age:20} (&student2).increaseAge(3) fmt.Println(student2.age) //25}
四、变量总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
全局变量的声明必须使用var关键词,局部变量可以省略;同一行可以声明多个变量。写法如下:
package mainimport ( "fmt")/*变量声明赋值*/var i1, i2, i3 int = 1, 2, 3var( a string = "hello world" b int)func main() { /*局部变量可以写成组的形式*/ var( c uint = 10 d string = "ddd" ) /*局部变量可以省略var,全局的不可以省略*/ e,f := 4,5 ……}
变量类型转化总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
GO中不存在隐式转换,类型转换必须是显示的,并且只能发生在两种兼容类型之间,例如:
var i1 int = 1var i4 float32 = float32(i1)
**注意:**大写字母开头的变量是可以导出的,也就是可以被其它包读取,是公用变量;
小写字母开头的是不可导出的,是私有变量。
五、常量总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
常量范围目前只支持布尔型、数字型、字符型。常量定义从形式上可以分为显示和隐式:
显示:const const_name1 type = value隐式:const const_name2 = valueconst MY_CONSTAT1 string = "hello world"const MY_XONSTANT2 = "HELLO CHINA"const (MY_CONSTANT3 string ="hello go"MY_CONSTANT4 = "hello GO")const language1,language2,language3 string = "go","java","python"
特殊常量iota的用法总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
iota在关键字const出现时被重置为0, const中每新增一行常量声明将使iota的计数加1。例如:
package mainimport "fmt"const a = iota/*b、c、d中只出现了一次const,所以b、c、d累加1*/const(b = iotac = iotad = iota)func main() {fmt.Println("a的值为:")fmt.Print(a) /*a的值为0*/fmt.Print("\n")fmt.Println("b的值为:")fmt.Print(b) /*b的值为0*/fmt.Print("\n")fmt.Println("c的值为:")fmt.Print(c) /*c的值为1*/fmt.Print("\n")fmt.Println("d的值为:")fmt.Print(d) /*d的值为2*/fmt.Print("\n")
iota的常见用法:
1、跳值使用法
package mainimport "fmt"const a = iotaconst(b = iotac = iota/*用_把2跳过去*/_ = iotad = iota)func main() {fmt.Println("a的值为:")fmt.Print(a) /*a的值为0*/fmt.Print("\n")fmt.Println("b的值为:")fmt.Print(b) /*b的值为0*/fmt.Print("\n")fmt.Println("c的值为:")fmt.Print(c) /*c的值为1*/fmt.Print("\n")fmt.Println("d的值为:")fmt.Print(d) /*d的值为3*/fmt.Print("\n")}
2、插队使用法
package mainimport "fmt"const(b = iota/*c插入b和d之间,b=0, d=2*/c = 5.12d = iota)func main() {fmt.Println("b的值为:")fmt.Print(b) /*b的值为0*/fmt.Print("\n")fmt.Println("c的值为:")fmt.Print(c) /*c的值为5.12*/fmt.Print("\n")fmt.Println("d的值为:")fmt.Print(d) /*d的值为2*/fmt.Print("\n")}
3、表达式隐式使用法
package mainimport "fmt"const(b = iota * 2/*c和d隐式的继承iota * 2*/cd)func main() {fmt.Println("b的值为:")fmt.Print(b) /*b的值为0*/fmt.Print("\n")fmt.Println("c的值为:")fmt.Print(c) /*c的值为2*/fmt.Print("\n")fmt.Println("d的值为:")fmt.Print(d) /*d的值为4*/fmt.Print("\n")}
4、单行使用法
package mainimport "fmt"const(/*iota在同一行不累加1,所以a=0, b=0+4=4*/a, b = iota, iota + 4/*c, d隐式继承a,b的格式,c=1, d=1+4=5*/c, d/*e等于2,注意e必须赋值,因为e不能隐式继承,因为格式不同*/e = iota)func main() {fmt.Println("a的值为:")fmt.Print(a) /*a的值为0*/fmt.Print("\n")fmt.Println("b的值为:")fmt.Print(b) /*b的值为4*/fmt.Print("\n")fmt.Println("c的值为:")fmt.Print(c) /*c的值为1*/fmt.Print("\n")fmt.Println("d的值为:")fmt.Print(d) /*d的值为5*/fmt.Print("\n")fmt.Println("e的值为:")fmt.Print(e) /*e的值为2*/
fmt.Print("\n")
六、流程控制
1、if条件判断
示例一:
package mainimport "fmt"func main() {var num int = 10if num > 10{fmt.Println("num is bigger than 10")}else {fmt.Println("num is not bigger than 10")}}
实例二:总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
package mainimport "fmt"func main() {var num int //默认值为0if num := 20; num > 10{ //此地的num为if模块的局部变量,只在if模块使用,会覆盖全局的num值fmt.Println("num is bigger than 10") //此地num值为20}else {fmt.Println("num is not bigger than 10") //此地num值为20}fmt.Println("num 的值为:")fmt.Println(num) //此地打印出的num为全局的num,值为0}
2、switch条件语句
go语言的switch…case语句中,只要匹配到case中一条,就只执行该case,执行完就自动跳出,不像C语言需要在每个case执行完加break语句,否则会继续向下执行其它case语句。
示例一:总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
package mainimport "fmt"func main() {var str string = "c"switch str {case "a":fmt.Println("str的值为a")case "b":fmt.Println("str的值为b")case "c": //只执行该casefmt.Println("str的值为c") //输出:str的值为cdefault: //当没有一个case满足时,执行fmt.Println("str的值为其它")}}
示例二:
package mainimport "fmt"func main() {var str string = "c" /*c为全局变量,值为c*/switch str := "b"; str { //局部变量str的值为b,会覆盖全局变量的ccase "a":fmt.Println("str的值为a")case "b":fmt.Println("str的值为b") //str的值为bcase "c":fmt.Println("str的值为c")default:fmt.Println("str的值为其它")}fmt.Println(str) //c 局部变量的值并不会改变全局的值,所以str的值依旧为c}示例三:case 说明符package mainimport "fmt"func main() {var num int = 10switch i := interface{}(num).(type){case int8 :fmt.Println(i)fmt.Println("num的类型为int8")case int16:fmt.Println(i)fmt.Println("num的类型为int16")case int32:fmt.Println(i)fmt.Println("num的类型为int32")case int64:fmt.Println(i)fmt.Println("num的类型为64")case int:fmt.Println(i) //10fmt.Println("num的类型为int") //num的类型为intdefault:fmt.Println("num其它类型")}}3、for语句示例1:循环输出package mainimport "fmt"func main() {for i := 0; i < 5; i++ {fmt.Println(i)}}示例二:for语句中用rangerange每次迭代都会返回两个值,一个是索引,一个索引处所代表的值package mainimport "fmt"func main() {var str string = "GO语言"for i,c := range str{fmt.Printf("%d : %c\n", i, c)}}输出:0 : G1 : O2 : 语5 : 言
因为go语言中所有字符和汉字都是用utf-8进行编码的,一个汉字占3个字节,range返回的“语”和“言”都是第一个字节作为索引。
range可以迭代字符串类型,数组类型,数组的指针类型,切片类型,字典类型,通道类型。
对于字符串类型,数组类型,数组的指针类型,切片类型,range每次迭代出两个值,第一个代表迭代处的索引,第二个值代表迭代处的值;
对于字典类型,range每次也迭代出两个值,第一个代表键,第二个代表键对应的内容,注意迭代不能保证顺序;
for语块中可以用break或continue,用法通C语言。
七、异常处理总结送免费学习资料(包含视频、技术学习路线图谱、文档等)
Go 语言通过内置的错误接口提供了非常简单的错误处理机制,error类型是一个接口类型,这是它的定义:
type error interface {Error() string}
在实际应用中,可以抛出系统的异常,也可以抛出指定的异常,示例如下:package mainimport ("errors""fmt""os")func isFileExist(path string) (bool, error) {if path == "" {return false, errors.New("传入路径为空") //返回自定义的错误}_, err := os.Stat(path)if err != nil {return true, err //返回系统的错误}return false, errors.New("未知的错误") //返回自定义的错误}func main() {path := ""flag, err := isFileExist(path)fmt.Println(flag) //输出:falsefmt.Println(err.Error()) //输出:传入路径为空
也可以自己实现Error接口,并自定义错误,示例如下:package mainimport "fmt"type My struct {age int}func (my *My) Error() string {str := `除数不能为0: %d / 0`return fmt.Sprintf(str,(*my).age)}func divideError(my1 *My, my2 *My) (result int, erroMsg string) {if my2.age == 0 {return 0, my1.Error()}else {return my1.age / my2.age, ""}}func main() {var my1 *Myvar my2 *Mymy1 = &My{25}my2 = &My{0}num, err := divideError(my1, my2)fmt.Println(num) //输出:0fmt.Println(err) //输出:除数不能为0: 25 / 0}
总结:比如my1是struct类型的指针,调用内部元素时,可以通过(*my1).age,也可以通过my1.age,因为go会自动进行类型推断
更多学习资料(包含视频、技术学习路线图谱、文档等)
技术点包含了C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等方面。
后台私信《资料》免费领取