go基础知识(一)语法
一:第一个go程序:
package main
import "fmt"
func main() {
/* 输出Hello, World!*/
fmt.Println("Hello, World!")
}
运行一下:输出:Hello, World!
$ go run hellow.go Hello, World!编译成二进制文件:
cjs@LAPTOP-UQTQL6TT MINGW64 /f/go $ go build hellow.go cjs@LAPTOP-UQTQL6TT MINGW64 /f/go $ ls hellow.exe* hellow.go cjs@LAPTOP-UQTQL6TT MINGW64 /f/go $ ./hellow.exe Hello, World!
知识点:
1:package:包,每一个go源文件开头都必须有1个或多个package声明,表示源文件所属包,Go 语言的编译程序会试图把这种名字的包编译为二进制可执行文件。所有用 Go 语言编译的可执行程序都必须有一个名叫 main 的包。一个可执行程序有且仅有一个 main 包。main()函数是程序的入口。
2:import:导入一个包,fmt 包使用函数实现 I/O 格式化(类似于 C 的 printf 和 scanf 的函数)。
3:func:函数,相当于php中的function
4:func main(){ 这里一定要注意,这个 { 不能单独一行。比如以下是错的:
func main() { //这种写法是错的,{ 不能单独一行。 }
5:注释:/* */ 或者//,这个和PHP差不多
6:go run:执行go程序
7:go build:编译打包代码为exe可执行程序
二:语言结构
go语言包括以下几个部分:包声明,引入包,函数,变量,语句 & 表达式,注释
三:基本语法
1:行分隔符:php每行结束是分号标识,G语言不需要,除非多个语句写在一行,那么中间用分号隔开,但这种写法不提倡,看起来不人性化。
2:标识符:标识符用来命名变量、类型等程序实体。字母、数字和下划线组成,但第一个字必须是字母或下划线。
3:字符串连接:通过+连接,比如:fmt.Println("Chinese" + "Kung Fu")
四:数据类型
php是弱类型语言,不必向 PHP 声明该变量的数据类型;而go是强类型定义语言,但和java又不一样,go可以定义数据类型,如:var name string = "李小龙",也可以不定义数据类型。个人理解:强类型定义语言,不是必须要声明类型,而是一旦声明了类型,如果不强制转换,那么它永远就只是这个数据类型。PHP开发就比较随意 $name = "李小龙",$name = 123 赋值不同,变量类型就变了。
五:变量与常量
1;变量:php中声明一个变量,是$符号开始,go语言一般用var,三种变量定义。
(1):指定变量数据类型
//声明字符串变量name var name string //声明多个变量 var name,name2,name3 string //如果没有初始化,则变量默认为零值 //声明字符串变量name,初始化值为:李小龙 var name string = "李小龙"(2):不指定变量类型
package main import "fmt" func main() { var d = 123 //没指定变量类型 fmt.Println(d) }编译器自己判断数据类型
(3):短变量
用来声明和初始化函数内部的局部变量,变量的类型根据表达式自动推导,不能在函数外面使用,而且声明了必须要使用。
package main import "fmt" func main() { var v int = 0 v := 1 // 错误 v已经声明过 fmt.Println(v) }
再看一个:
package main import "fmt" func main() { var v int = 0 // 正确 v虽然已经声明过,但是b没有, //所以多个变量声明,左边至少要有一个新变量 v,b:= 1,2 fmt.Println(v) //错误,声明的变量必须使用,这里b没有实际用到 fmt.Println(v,b) //正确,输出了v和b,使用了变量 }
2:常量
常量用const定义。
const b string = "abc" //显式类型定义 const b = "abc" //隐式类型定 //多个相同类型的声明可以简写为: const c_name1, c_name2 = value1, value2
六:运算符和PHP差不多,略
七:基本语句
(1):if else
package main import "fmt" func main() { /* 局部变量定义 */ var a int = 100; /* 判断布尔表达式 */ if a < 20 { /* 如果条件为 true 则执行以下语句 */ fmt.Printf("a 小于 20\n" ); } else { /* 如果条件为 false 则执行以下语句 */ fmt.Printf("a 不小于 20\n" ); } fmt.Printf("a 的值为 : %d\n", a); }(2):for语句,输出1到100,go没有while语句
package main import "fmt" func main() { var count = 0 for count < 100{ count++ fmt.Println(count) } }break:用于中断当前 for 循环或跳出 switch 语句。
continue:跳过当前循环的剩余语句,然后继续进行下一轮循环。
goto:将控制转移到被标记的语句。
八:函数
在php中函数以function标识,go语言中用func,在go程序中必须要有mian函数,程序从这里执行,如果不需要返回值可以不用返回类型,否则需要指定返回类型。
1:基本调用
package main import "fmt" func main(){ //程序开始 var a int = 100 var b int = 200 var count int count = sum(a,b) //调用sum函数 fmt.Printf("相加为:%d\n",count) } func sum(num1 int,num2 int) int{ //返回类型 return num1+num2 } // 类型不一样,转换 package main import "fmt" func main(){ var a int = 100 var b float64 = 200.2 var count float64 count = sum(a,b) fmt.Printf("相加为:%f\n",count) } func sum(a int,b float64) (float64){ return float64(a)+b // a强制转换为float }
2:多个返回值
package main import "fmt" func main(){ a,b := "china","shenzhen" a,b = swap(a,b) fmt.Println(a,b) } func swap(x,y string) (string,string){ return x,y }
3:入参和返回值不一样
package main import "fmt" func main(){ a,b := "china","shenzhen" var c string a,b,c = swap(a,b) //返回3个,入参2个 fmt.Println(a,b,c) } func swap(x,y string) (string,string,string){ return x,y,"中国晚上" // 返回3个 }
九:数组
go 语言数组,三种定义方式。
package main import "fmt" func main() { var n[10] int /* 长度为10的数组*/ var i,j int /* 数组n初始化值 */ for i = 0; i<10; i++ { n[i] = i+1 } /* 输出每个数组元素值*/ for j = 0; j<10; j++ { fmt.Printf("n[%d] = %d\n",j,n[j]) } }
一些基本用法:
var arr1 [3] int //3个int型的数组,初始值是3个0,定义了数组长度,就不能改 arr2:=[5]int{1,2,3,4,5} //定义并初始化长度为5的数组,赋值5个。 arr3:=[5]int{1,2,3} //定义并初始化长度为5的数组,最后两个没赋值为0 var arr2 = [...]int{6, 7, 8} //不声明长度 q := [...] int {1,2,3} //不声明长度 r := [...] int {99:-1} //长度为100的数组,只有最后一个是-1,其他都是0函数定义的返回值和实际返回值要一致
十:指针
一个指针变量指向了一个值的内存地址,取地址符加&,如取变量a的内存地址:&a
十一:结构体struct
结构体可以定义不同的数据类型(数组就做不到),把各种不同类型的数据组合在一起,属于一种聚合类型。
语法结构:type 名称 struct{}
(1):基本用法
package main import "fmt" type Books struct{ //定义结构体 title string subject string book_id int } func main(){ //结构体元素赋值输出 //这里变量类型为结构体的名称:Books //或者短变量写法 data := Books{"go语言","语言教程",1} var data Books = Books{"go语言","语言教程",1} fmt.Println(data) //key value格式 fmt.Println(Books{title:"go语言",subject:"语言教程",book_id:1}) //不赋值字段为0或者空 fmt.Println(Books{title:"go语言",subject:"语言教程"}) }
(2):访问结构体成员
访问结构体成员用 . 符号,格式:结构体.成员名
package main import "fmt" type Books struct{ //定义结构体 title string } func main(){ //结构体元素赋值输出 var books Books //声明books为 Books 这里用new也可以 books := new(Books) books.title = "go语言" //成员赋值 fmt.Println(books.title) //打印 }
这里就好比php中面向对象用$this->给变量赋值,取值,这里就用 .
(3):结构体作为函数参数
package main import "fmt" type Books struct{ //定义结构体 title string name string } func main(){ //结构体元素赋值输出 var books Books //声明books为 Books books.title = "go语言" //赋值 books.name = "李小龙" //赋值 abs(books) //调用abs函数 } func abs(books Books){ //类型为Books fmt.Println(books.title) fmt.Println(books.name) }
(4)结构体方法:
基本格式:
package main import "fmt" type Point struct{ name string age int } /* 1:结构体方法比普通方法声明多了一个参数,把方法绑定在此参数上。 2:此参数为:p 又叫接收器,为某种类型的变量,display为方法 3:接收器范围:方法绑定到除了指针类型和接口类型的任何类型上 4:格式为: func (接收器变量 接收器类型) 方法名(参数列表) (返回参数) { 函数体 } */ func (p Point) display() { // 只有Point实例可以调用 display方法 fmt.Println(p.name,p.age) } func main(){ p := Point{ name:"李小龙", age:27, } p.display() }十二:语言切片Slice
slice相当于动态的数组,go语言中数组长度不能改变,实际使用中不实用。比如把数据库某些数据提出来,提到数组中,这些数据是动态的,甚至长度可能是不知道的,用数组就没法弄。slice长度是不固定的,可以追加元素。
基本语法:
(1)var 切片名 []type = make([], len, [cap]);参数说明:type是数据类型、len是大小、cap是切片容量(容量必须>=长度)
(2)var 变量名 []变量类型
什么是容量和长度:举个例子,一个杯子可以装500ml水,现在杯子里面有200ml水。容量:500ml,长度:200ml。容量就是杯子的容量,而长度就是杯子实际装了多少。所以这就是容量为啥必须大于等于长度的原因。
通过三种方法创建切片:
// 1:make创建切片,分配内存,初始化 var arr = make([]int,5,10) // make函数长度为5,容量为10 var arr = make([]int,5) //长度为5,容量可以不写 // 2:new 创建切片,只分配内存,不初始化,返回指针 arr := new([]int) *arr = append(*arr, 1, 2, 3,4,5,6) //追加 fmt.Println(*arr) // 3:直接写 var arr = [] int {1,2,3} , // []里面有值就是数组,否则就是切片 arr = append(*arr, 4,5,6)追加元素
func main() { s := make([]int, 3) //定义长度为3的切片 这里输出为 0 0 0 s = append(s, 1, 2, 3) //追加3个元素 fmt.Println(s) //结果为 0 0 0 1 2 3 }len() 和 cap() 函数获取长度和容量
func main() { s := make([]int, 3) //定义长度为3的切片 这里输出为 0 0 0 s = append(s, 1, 2, 3) //追加3个元素 fmt.Println(len(s),cap(s)) //分别输出切片长度和容量 }
截取
func main() { var s = []int{1,2,3,4,5} // : 符号在左边,表示从头截取到第3个为止,输出:[1 2 3] fmt.Println(s[:3]) // : 符号在右边,表示截取第3个以后的,输出:[4 5] fmt.Println(s[3:]) // : 符号在中间,表示截取1和3之间的,输出:[2 3] fmt.Println(s[1:3]) }
复制拷贝
/* 拷贝 numbers 的内容到 numbers1 */ copy(numbers1,numbers)
十三:range 关键字key-val
func main(){
nums := []int{2, 3, 4}
count := 0
// 循环nums
for _, val := range nums { // _下划线表示不输出索引
count += val //累加
}
fmt.Println("sum:", count) //输出 9
}
func main() { nums := []int{2, 3, 4} // 循环nums for i, v := range nums { // i 为key nums[i] = v fmt.Println("index:", i) //输出key } }
// 字符串遍历 var str = "hello 你好" for key, value := range str { fmt.Printf("key:%d value:%c\n", key, value) // %c:输出给定整数的对应字符 }