语言特性
- 高性能、高并发
- 语法简单,学习曲线平缓
- 有丰富的标准库
- 有完善的工具链
- 支持静态链接
- 支持快速编译
- 跨平台支持
- 支持垃圾回收
以下是一个基于Go语言的http服务器实例:
package main
import "net/http"
func main() {
http.Handle("/", http.FileServer(http.Dir(".")))
http.ListenAndServe(":8080", nil)
}
基本结构
- 包声明:
package main - 引入包:
import "fmt" - 函数:
func main - 变量:
var i int - 语句&表达式:
fmt.Println(i) - 注释:
/*这是一个简单的程序*/
语法
行分隔符
Go程序中,每一行代表一个语句的结束,类似Python;如果要将多个语句写在同一行,则两条语句之间需要用分号隔开。
e.g:
fmt.Println("HHW")
fmt.Println("runoob")
注释
// 单行注释
/*
Author by 菜鸟教程
我是多行注释
*/
标识符
禁止的标识符类型:
- 数字开头
- Go语言的关键字
- 不能携带运算符
字符串
连接
通过+实现。
e.g:
package main
import "fmt"
func main() {
fmt.Println("Google" + "Runoob")
}
输出结果:
GoogleRunoob
格式化
Go语言使用fmt.Printf或fmt.Sprintf格式化字符串并赋值给新串。
- Sprintf 根据格式化参数生成格式化的字符串并返回该字符串。
- Printf 根据格式化参数生成格式化的字符串并写入标准输出。
Sprintf实例:
package main
import (
"fmt"
)
func main() {
// %d 表示整型数字,%s 表示字符串
var stockcode=123
var enddate="2020-12-31"
var url="Code=%d&endDate=%s"
var target_url=fmt.Sprintf(url,stockcode,enddate)
fmt.Println(target_url)
}
输出结果:
Code=123&endDate=2020-12-31
Printf实例:
package main
import (
"fmt"
)
func main() {
// %d 表示整型数字,%s 表示字符串
var stockcode=123
var enddate="2020-12-31"
var url="Code=%d&endDate=%s"
fmt.Printf(url,stockcode,enddate)
}
输出结果:
Code=123&endDate=2020-12-31
操作
具体的操作如下实例所示:
func main{
a:="hello"
fmt.Println(strings.Contains(a,"ll"))//true
fmt.Println(strings.Count(a,"l"))//2
fmt.Println(strings.HasPrefix(a,"he"))//true
fmt.Println(strings.HasSuffix(a,"llo"))//true
fmt.Println(strings.Index(a,"ll"))//2
fmt.Println(strings.Join([]string{"he","llo"},"-"))//he-llo
fmt.Println(strings.Repeat(a,2))//hellohello
fmt.Println(strings.Replace(a,"e","E",-1))//hEllo
fmt.Println(strings.Split("a-b-c","-"))//[a b c]
fmt.Println(strings.ToLower(a))//hello
fmt.Println(strings.ToUpper(a))//HELLO
fmt.Println(len(a))//5
b:="你好"
fmt.Println(len(b))//6 每个中文字符被记录为3个字符
}
解析字符串
使用"strconv"包进行解析。
关键字
Go语言常用的25个关键字/保留字如下:
| break | default | func | interface | select |
|---|---|---|---|---|
| case | defer | go | map | struct |
| chan | else | goto | package | switch |
| const | fallthrough | if | range | type |
| continue | for | import | return | var |
Go语言的36个预定义标识符如下:
| append | bool | byte | cap | close | complex |
|---|---|---|---|---|---|
| complex64 | complex128 | uint16 | copy | false | float32 |
| float64 | imag | int | int8 | int16 | uint32 |
| int32 | int64 | iota | len | make | new |
| nil | panic | uint64 | println | real | |
| recover | string | true | uint | uint8 | uintptr |
关于空格的使用
Go 语言中变量的声明必须使用空格隔开。
变量
常量
Go语言中的常量const没有固定的类型,可以自动根据上下文来确定类型。
数组
Go语言中的数组是具有编号且长度固定的元素序列。创建方式:var 数组名 [数组大小] 数据类型。
由于其长度固定,在日常使用中我们用的更多的是切片。
切片 (slice)
本质是可变长度的数组,可以随时更改其长度。
创建方式:切片名 := make([]数据类型, 初始长度)
可以使用append语句来追加元素。追加方式:原来的切片名 = append(原来的切片名, 新加的数据)。
有类似于python的切片提取功能,用法示例:fmt.Println(数组名[要切片的范围])。
可以使用copy语句实现数组的复制,用法:
s:=make([]string,3)
c:=make([]string,len(s))
copy(c,s)
逻辑语句
if else
Go语言中的if else语句格式如下:
package main
import "fmt"
func main(){
if 7%2 == 0{
fmt.println("7 is even")
} else {
fmt.println("7 is odd")
}
}
注意: Go语言中if语句后面是不带括号的。
循环语句
Go语言中仅有for循环
以下是一个for循环的实例:
package main
import "fmt"
func main(){
i:=1
for{
fmt.Println("loop")//不加break就是死循环
break
}
for j:=7;j<9;j++{
fmt.Println(j)
}
for n:=0;n<5;n++{
if n%2==0 {
continue
}
fmt.Println(n)
}
for i<=3{
fmt.Println(i)
i=i+1
}
}
输出结果如下:
loop
7
8
1
3
1
2
3
分支语句
switch语句
Go语言中的switch语句有如下特点:
- 大体上和C++类似
- switch后面的语句不需要加括号
- 每个case不需要添加
break语句,执行完一个case会直接跳出分支语句 - switch后可以使用任意的变量类型
以下是一个switch语句实例:
package main
import (
"fmt"
"time"
)
func main(){
a:=2
switch a{
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
default:
fmt.Println("other")
}
t:=time.Now()
switch {//switch后面可以不加判断,直接在case语句中进行判断
case t.Hour()<12://可以直接在case后面加判断语句
fmt.Println("It's before noon")
default:
fmt.Println("It's afternoon")
}//整个的功能可以用于替换if else语句
}
map结构
实际使用过程中可能(?)是最频繁的数据结构。其他语言可能称之为哈希或字典。私以为是建立了两个数据之间的联系。
以下是一个map的实例:
func main(){
m:=make(map[string]int)//string是key的类型,int是value的类型
m["one"]=1
m["two"]=2
fmt.Println(m)//map[one:1 two:2]
fmt.Println(len(m))//2
fmt.Println(m["one"])//1
fmt.Println(m["two"])//0
r,ok:=m["unknow"]
fmt.Println(r,ok)//0 false
delete(m,"one")
m2:=map[string]int{"one":1, "two":2}//直接赋值
var m3=map[string]int{"one":1, "two":2}//也可以用var语句,两者功能一致
fmt.Println(m2,m3)//map[one:1 two:2] map[one:1 two:2]
}
range语句
可以用来快速遍历map结构。采用range后会返回两个值,第一个是索引,第二个是对应位置的值。
以下是一个range的实例:
func main() {
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num) //index:0 num:2
}
}
fmt.Println(sum) //9
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println(k, v) //b 8;a A
}
for k := range m {
fmt.Println("key", k) //key a;key b
}
}
函数的使用
Go语言的函数数据类型是后置的,函数原生支持返回多个值。一般情况下会返回两个结果:真正的结果 + 错误信息 。
指针
Go语言指针的操作相比C++非常有限,主要用途就是对常用的参数进行修改。
设定数据类型和参与运算时需要在数据类型前加上*,在输出结果时需要在变量名前加上&。
结构体
相当于是将几个变量打包成一个变量组。
以下是一个结构体实例:
type user struct {
name string
password string
}
func checkPassword(u user, password string) bool {
return u.password == password
}
func checkPassword2(u *user, password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string){//类似于Java中的类成员函数
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
b := user{"wang", "1024"}
c := user{name: "wang"}
c.password = "1024"
var d user
d.name = "wang"
d.password = "1024"
fmt.Println(a, b, c, d)//{wang 1024}(wang 1024}{wang 1024}{wang 1024}
fmt.Println(checkPassword(a, "haha")) //false
fmt.Println(checkPassword2(&a, "haha")) //false
a.resetPassword("2048")//此处调用了结构体方法
}
错误处理
Go语言相比Java的异常处理,能够清晰的知道是哪个函数发出了错误信息。
通过在函数的返回值中添加一个error变量,从而获取到实际的错误信息。
JSON处理
对于一个已有的结构体,如果其变量名首字母均为大写,即可使用json.Marshal进行序列化操作,序列化后会变成一个buf数组。若要输出字符,需要使用string(buf)进行强制类型转换。也可以使用json.Unmarshal实现反序列化到一个空变量中。
时间的处理
最常用的是time.Now()获取当前时间,也可以使用time.Date(YYYY, MM, DD, HH, MM, SS, +x, time.timeReigon)来构造一个具有时区的时间。
获取时间段:time2.Sub(time1)语句。输出一个时间段,得到其时分秒值。
利用time.Format("2006-01-02 15:04:05")来格式化一个时间字符串;同样地,可以用time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:29")语句来解析一个时间字符串。
可以利用now.Unix()来获取一个时间戳。