- 基础语法--hello world!
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
package main表示该文件属于main包的一部分,mian包即程序的入口包,该文件即程序的入口文件。
导入标准库的fmt包:主要往屏幕输入输出字符串,格式化字符串(该操作类似C的导入头文件)
func main 即主函数,调用fmt的Println输出
运行该程序使用go run命令
生成二进制文件使用go build命令
鼠标放在Println上可以链接跳转包的官方文档,查看其他方法的使用方法,类似idea
- 基础语法--变量
字符串是内置类型,类似string,可以直接用 + 拼接,也可以用 = 去比较两个字符串
变量的声明:var 【name】 = 【value】
比如: var a = "initial"
会根据value自动匹配变量的类型,如果想直接确定类型,可以在【name】后直接将类型名标注
比如: var b, c int = 1, 2
或者【变量名】 := 【value】
声明常量时,将var改为const
可以声明多个类型不同的变量(类型由初始化表达式推导):
var i, j, k int // int, int, int
var b, f, s = true, 2.3, "four"// bool, float64, string
package main
import (
"fmt"
"math"
)
func main() {
var a = "initial"
var b, c int = 1, 2
var d = true
var e float64
f := float32(e)
g := a + "foo"
fmt.Println(a, b, c, d, e, f) // initial 1 2 true 0 0
fmt.Println(g) // initialfoo
const s string = "constant"
const h = 500000000
const i = 3e20 / h
fmt.Println(s, h, i, math.Sin(h), math.Sin(i)) // constant 500000000 6e+11 -0.28470407323754404 0.7591864109375384
}
- 基础语法--switch
go语言中Switch后面的变量名和if一样不需要括号,和C语言不同的是,C语言case语句后没有break默认走完所有case,而go语言默认是不走的。
在go中Switch还有更加高级的用法,可以在Switch后不加任何的变量名,而在case后添加条件判断,可以代替if语句使条件的选择更加清晰,代码更加美观。
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")
case 4, 5:
fmt.Println("four or five")
default:
fmt.Println("other")
}
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
}
- 基础语法--map
使用过程中用到的最多的数据结构,使用make创建
m :=make(map[string]int)
m["one"] =1
m["two"] =2
其中string是key的类型,int是value的类型,初始化一些map中的值
ages :=map[string]int{
"alice": 31,
"charlie": 34,
}
使用delete去删除
delete(m, "one")
在使用时可以在变量后面加一个ok来获取对应key索引的value是否存在如果存在变量为value,ok为true,否则,变量为对应类型的零值,ok为false
r, ok :=m["unknow"]
fmt.Println(r, ok) // 0 false
map是无序的,多次迭代会得到不同的结果。
- 基础语法--range
一个迭代工具,可以快速遍历数组,切片,map等,类似java的foreach快速遍历
在迭代时可以同时输出对应的key和value
如果不需要索引可以用下划线free
package main
import "fmt"
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语言也有指针,其使用形式大致和Cpp相同,但功能相对简单,一般用于函数间传参时改变变量的值,传参时用&,解引用时用*
但要注意的是,go语言是不支持指针运算的,如果想进行指针运算,需要引入特殊包,直接对内存进行操作
- 基础语法--错误处理
错误,一种类似java中的异常却不完全相同的类型
go语言通常将错误作为返回值
不同于java的异常,go的错误会清楚的显示错误发生的行与列,并能通过简单的if else语句初期错误
例如,在参数列表中加入err类型,如果返回正常,error即返回nil,否则,new一个错误并返回
在主函数中同样也要有变量来接收err的值,并主函数中对错误进行相应的处理以保证程序的稳定性
package main
import (
"errors"
"fmt"
)
type user struct {
name string
password string
}
func findUser(users []user, name string) (v *user, err error) {
for _, u := range users {
if u.name == name {
return &u, nil
}
}
return nil, errors.New("not found")
}
func main() {
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name) // wang
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err) // not found
return
} else {
fmt.Println(u.name)
}
}
- 基础语法--字符串操作
在go语言的strings包里包含了许多有关于字符串的操作,需要使用时导包即可
Contains:查找是否包含某一字符串,返回布尔值
Count:统计某个字符串在原字符串中出现的次数
Index:定位
Join:将一个字符串拼接到另一个字符串后面
Repeat:重复多次字符串
len:内置函数,统计字符串中的字符个数,注意中文可能一个字对应多个字符
package main
import (
"fmt"
"strings"
)
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
}
- 基础语法--字符串格式化
在标准库fmt下就有字符串格式化函数,常见的有Println,打印并换行。还有熟悉的C语言中的Printf,其语法和C语言类似,比较方便的一点是,go语言只需要%v即可输出任意类型数据。可以用%+v , %#v来得到更加详细的结构。
package main
import "fmt"
type point struct {
x, y int
}
func main() {
s := "hello"
n := 123
p := point{1, 2}
fmt.Println(s, n) // hello 123
fmt.Println(p) // {1 2}
fmt.Printf("s=%v\n", s) // s=hello
fmt.Printf("n=%v\n", n) // n=123
fmt.Printf("p=%v\n", p) // p={1 2}
fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}
f := 3.141592653
fmt.Println(f) // 3.141592653
fmt.Printf("%.2f\n", f) // 3.14
}
- 基础语法--json处理
定义结构体时,所有变量用大写
给结构体赋值后,用Marshal进行序列化,或者用MarshalIndent函数产生整齐缩进的序列化
输出时,用string做强制类型转换,否则输出为一串16进制编码
也可以用Unmarshal函数进行反序列化,将json数据解码为字节切片
如果在输出时想让输出与结构体成员名不同,需要在结构体声明时在对应结构体成员后加tag标签进行标注
package main
import (
"encoding/json"
"fmt"
)
type userInfo struct {
Name string
Age int `json:":age"`
Hobby []string
}
func main() {
a := userInfo{
Name: "wang",
Age: 18,
Hobby: []string{"Golang", "TypeScript"},
}
buf, err := json.Marshal(a)
if err != nil {
panic(err)
}
fmt.Println(buf) // [123 34 78 97 ...]
fmt.Println(string(buf)) // {"Name":"wang",":age":18,"Hobby":["Golang","TypeScript"]}
buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(buf))
// {
// "Name": "wang",
// ":age": 18,
// "Hobby": [
// "Golang",
// "TypeScript"
// ]
//}
var b userInfo
err = json.Unmarshal(buf, &b)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", b) // main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}
}
- 基础语法--时间处理
时间的处理要引入time包
通过time.Now()获取当前时间
通过time.Date去构造一个带时区的时间
构造完成后可以用【变量名】.Year , 【变量名】.Month 等等去获取时间中的年月日时分秒
Sub函数将两个时间相减获得到时间差 用.Minutes(),.Seconds()可以将时间差转换为分,秒
时间格式化,必须将"2006-01-02 15:04:05"放入,否则不成功
这里有两种格式化方法:
t.Format("2006-01-02 15:04:05")
t3, err :=time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")
在系统交互时,可以用.Unix()去获取一个时间戳
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
fmt.Println(now) // 2022-03-27 18:04:59.433297 +0800 CST m=+0.000087933
t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC)
fmt.Println(t) // 2022-03-27 01:25:36 +0000 UTC
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()) // 2022 March 27 1 25
fmt.Println(t.Format("2006-01-02 15:04:05")) // 2022-03-27 01:25:36
diff := t2.Sub(t)
fmt.Println(diff) // 1h5m0s
fmt.Println(diff.Minutes(), diff.Seconds()) // 65 3900
t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")
if err != nil {
panic(err)
}
fmt.Println(t3 == t) // true
fmt.Println(now.Unix()) // 1648738080
}
- 基础语法--数字解析
对于字符串和数字的转化解析,需要引入strconv包
使用ParseFloat将字符串转化为浮点数,64代表精度
f, _ :=strconv.ParseFloat("1.234", 64)
fmt.Println(f) // 1.234
使用ParseInt将字符串转化为整数,第二个参数代表进制,如果为0代表自动推测,64代表精度
n, _ :=strconv.ParseInt("111", 10, 64)
fmt.Println(n) // 111
n, _=strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n) // 4096
使用Atoi进行快速转化,也可以Itoa转化
package main
import (
"fmt"
"strconv"
)
func main() {
n2, _ := strconv.Atoi("123") // string转int
fmt.Println(n2) // 123
string_number := 97
result := strconv.Itoa(string_number) // int转string
fmt.Println(result)
fmt.Printf("%T\n", result)
}
如果失败会返回错误
n2, err :=strconv.Atoi("AAA")
fmt.Println(n2, err) // 0 strconv.Atoi: parsing "AAA": invalid syntax
- 基础语法--进程信息
要导入对应的os,os/exec包
os.Args:获取当前进程的命令行参数,命令行参数包括了程序路径本身,以及通常意义上的参数。程序中os.Args的类型是[]string
os.Getenv:检索由键命名的环境变量的值。它返回值,如果变量不存在,该值将为空。
os.Setenv: 函数可以设置名为 key 的环境变量,如果出错会返回该错误。
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
fmt.Println(os.Args) // [C:\Users\hp-pc\AppData\Local\Temp\GoLand___go_build_test_go.exe]
fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
fmt.Println(os.Setenv("AA", "BB")) // <nil>
buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
if err != nil {
panic(err)
}
fmt.Println(string(buf)) // 127.0.0.1 localhost
}