一、第一个程序
1.代码示例
package mainimport ("fmt")func main(){fmt.Println("hello world")}
2.手动执行
go run xx.go
3.编译为可执行程序
go build -o xx.exe xx.go
4.代码格式调整
idea:Ctrl+Alt+L
命令行: gofmt -w xxx.go
注意:如果在windows开发后需要打包成在linux可执行程序每次都需执行以下三步
set ENABLECGO=0 //该配置不是必须,请根据实际配置
set GOARCH=amd64
set GOOS=linux
go build -o xxx xx.go
二、语法要求
1.命名规范
1) package 名称要与文件名相同
2) 变量、函数名 严格区分大小写,首字母大写为公有(public),小写为私有(private)
3) _表示省略返回值
2.变量定义
//局部变量定义必须被引用,否则程序会报错var a = 1var c int = 1//:只可定义局部变量,不可定义全局b := 1//批量定义var (d = 1f = 1)//常量定义,不可被改变const FIRST_NUM = 1//const结合iotaconst (//iota默认为0,SECOND_NUM值为0SECOND_NUM = iota//定义iota后,下面的变量可不主动赋值,默认会根据iota+=1进行赋值,THREE_NUM值为1THREE_NUM//这里iota会遵从iota+=1的原则变为2,然后乘以10,最后赋值为20FOUR_NUM = iota * 10/*这里iota的值增长规则不变,还是iota+=1,这里iota值为3,由于上一步附加了*10的规则,这里FIVE_NUM值为30*/FIVE_NUM)
3.变量转换
package mainimport ("fmt""strconv")func main(){//类型转换需要进行显示的转换var i = 100var fi = float32(i)fmt.Println(fi)fmt.Printf("fi的类型为:%T",fi)fmt.Println()//int转字符串,参数一表示要转换的值,参数2表示转换的结果为几进制var strNum = strconv.FormatInt(10,10)fmt.Println(strNum)fmt.Printf("strNum的类型为:%T",strNum)fmt.Println()//字符转转int,参数一为要转换的值,参数二为转换的结果为几进制,//参数三bitSize指定结果必须能无溢出赋值的整数类型,0、8、16、32、64 分别代表 int、int8、int16、int32、int64var intNum, _ = strconv.ParseInt(strNum,2,0)fmt.Println(intNum)fmt.Printf("strNum的类型为:%T",intNum)fmt.Println()}
4.指针
package mainimport "fmt"func changeValue1(p *int) {//*p 指向地址存储的值*p = 10}func changeValue2(p int) {//p为局部变量,会创建新的地址p = 100}func main() {var a = 1//&a 获取a变量的指针地址changeValue1(&a)changeValue2(a)fmt.Println(a) //最终结果为10//指针类型的变量同样有地址,因此出现多重指针var pp = **intvar p = &app = &p}//make和new的区别//make和new都是用来申请内存的//make是给map、slice、chan进行内存申请的,返回的是对象本身。//new是给string、int等基本数据类型进行内存申请的,返回的是对应的指针类型,很少用
5.函数返回值
package mainimport ("fmt")//无参数返回func foo1(var1 int,var2 string) {fmt.Println("----foo1----")fmt.Println(var1,var2)}//返回一个参数func foo2(var1 int,var2 string) int {fmt.Println("----foo2----")fmt.Println(var2)return var1}//返回多个参数func foo3(var1 int,var2 string) (int,string) {fmt.Println("----foo3----")return var1,var2}//返回多个同类型参数,并对参数命名func foo4(var1,var2 int) (r1,r2 int) {fmt.Println("----foo4----")fmt.Println("r1=",r1,",r2=",r2)//当给返回参数命名后,该返回结果会默认为整个函数的局部变量,并赋予默认值.//若返回参数命名后可直接使用 return r1,r2,也可直接returnreturn var1,var2}func main(){foo1(100,"无参数返回")foo2Num := foo2(100,"返回一个参数")fmt.Println(foo2Num)foo3Num, foo3Str := foo3(100, "返回多个参数")fmt.Println(foo3Num, foo3Str)foo4Num1, foo4Num2 := foo4(1,2)fmt.Println(foo4Num1, foo4Num2)//_表示丢弃返回结果,直接垃圾回收_,_ = foo4(1,2)}
6.init函数和import的导包流程
import->const->var->init->main
7.import 导包
package main//两个包不可相互依赖,例如://A依赖B,B依赖A,如果出现该情况会报import cycle not allowed的错误import (//正常导包"fmt"//匿名导包,只会默认调用包内的init函数,其他函数无法调用_ "xxx"//别名导包,可以使用别名进行保内的函数调用mylib "xxx"//本地导包,无需使用别名,直接使用函数名即可调用保内函数. "xxxx")
8.defer关键字 (最后执行)
package mainimport "fmt"func return1() int {fmt.Println("--------return 1----------")return 1}func return2() int {fmt.Println("--------return 2----------")return 2}func execReturn() int {defer return1()//这里return 分为执行函数,返回结果两部,defer语句在这两步中间执行return return2()}func main() {defer fmt.Println("defer表示该语句最后执行,我相当于java的finally")defer fmt.Println("我是第二个defer,defer是先进后出,因此我不能最后打印")fmt.Println("我想最后执行")fmt.Println(execReturn())}
9.数组以及slice(动态数组)
package mainimport "fmt"//数组,值传递无法修改原数组的值func printArray1(array [4]int) {fmt.Println("普通数组")for index, value := range array {fmt.Println("index=", index, "value=", value)}}//slice(动态数组),引用传递func printArray2(array []int) {fmt.Println("slice-动态数组")for index, value := range array {fmt.Println("index=", index, "value=", value)}array[1]=1000}func main() {//定义数组var array1 [4]intvar array2 = [4]int{1, 2, 3, 4}var array3 = []int{1, 2, 3, 4}printArray1(array1)printArray1(array2)printArray2(array3)fmt.Println("slice可以在函数中修改值")for index, value := range array3 {fmt.Println("index=", index, "value=", value)}}
10.slice是使用注意事项
package mainimport "fmt"func printArray(array []int) {fmt.Println("-------------分割线------------")for index, value := range array {fmt.Println("index=", index, "value=", value)}}func main() {//slice声明的方式//方式一:声明一个slice,并非配两个空间,值为1,2array1 := []int{1, 2}printArray(array1)//方式二:声明一个slice,未分配空间,通过append分配空间并增加数值,默认值为nilvar array2 []intprintArray(array2)//方式三:通过make创建一个slice为slice分配指定大小空间,并设置初始扩容的cap值为10//如果不传入cap,初始cap与len相同//当len的大小超过cap时,cap会进行2倍扩容,当cap的数字大于1024后每次扩容以1.25倍进行扩容var array3 = make([]int, 1, 10)printArray(array3)if array3 == nil {fmt.Println("slice为nil")} else if len(array3) == 10 {fmt.Println("slice长度为10")} else {fmt.Println("slice不为nil")}//slice的使用//slice截取数组array4 := make([]int, 0)//追加数组元素array4 = append(array4, 1)array4 = append(array4, 2)array4 = append(array4, 3)array4 = append(array4, 4)//删除数组元素,表示将下标为1的元素删除,然后用下表为2的元素进1array4 = append(array4[:1], array4[2:]...)fmt.Println(len(array4))printArray(array4)//通过截取数组进行赋值,传递的是值引用,不是值,这里与python的规则不同,python传递的是值//如果想要值传递需要使用copy函数//在截取数据时,会以cap的数量为限定进行截取,比如len为3,cap为6你可以截取6个元素而不是3个//在截取数据前当原数组未进行删除时,大于len元素默认会赋值为0//如果原数组有进行删除,大于len的元素会以原数组未删除前下标的元素进行赋值不在为0fmt.Println(len(array4),cap(array4),&array4)array5 := array4[0:4]fmt.Println(len(array5),cap(array5),&array5)array5[0] = 100printArray(array4)printArray(array5)var array6 = make([]int,3)//通过copy进行slice深拷贝时,array6必须已分配等同的空间,否则会报错copy(array6, array4)array6[1] = 200printArray(array6)}
11.map使用
package mainimport ("fmt")//遍历func printMap(myMap map[string]string) {for key, value := range myMap {fmt.Println("key=", key, ",value=", value)}}//删除func deleteMap(myMap map[string]string, key string) {delete(myMap, key)}//新增func addMap(myMap map[string]string, key string, value string) {myMap[key] = value}//修改func updateMap(myMap map[string]string, key string, value string) {myMap[key] = value}func main() {//map的声明方式//方式一var map1 map[string]stringif map1 == nil {fmt.Println("map为空")}//方式二map2 := make(map[string]string, 10)map2["one"] = "first"//方式三map3 := map[string]string{"one": "first","two": "second",}deleteMap(map3,"one")printMap(map1)printMap(map2)printMap(map3)}
12.struct(结构体)
package mainimport "fmt"// User 自定义结构体type User struct {name stringage int}//结构提函数传递为值传递,因此需要设置指针专递才可修改结构体属性func changeUser(user *User) {user.age = 100}//类比于上方法,区别在于该方法属于struct结构体的方法,结构液体传递在这里同意规范使用指针传递//如果值传递,方法内对该结构体值进行修改不可同步至方法外边指针func (u *User)ChangeUser(){u.age=10}func main() {//定义结构体方式//方式一var user Useruser.name = "名字"user.age = 24//方式二var user1 = User{name:"名字",age:24}//方式三var user2 = User{"名字",24}fmt.Println(user)fmt.Println(user1)fmt.Println(user2)changeUser(&user)fmt.Println(user)//匿名结构体定义var u struct{Name string}u.Name="222"fmt.Println(u)}
13.interface
interface更多使用,请参考面向对象多态
package mainimport "fmt"//interface{}是万能数据类型func myFunc(arg interface{}) {fmt.Println("arg =", arg)//校验数据类型value, result := arg.(string)if result {fmt.Println("是字符串", value)} else {fmt.Println("不是字符串", value)}}func main() {myFunc(100)myFunc("string")}
