go语言基础语法
了解go语言
go是谷歌开发的一款编程语言,他相比于Java、c++等开发语言来说,go语言语法简单、编译快且轻
go语言优点
- 高性能、高并发
- 语法简单、学习曲线平缓
- 丰富的标准库
- 完善的工具链
- 静态链接
- 快速编译
- 跨平台
- 垃圾回收,也就是内存回收go语言会在进程结束时自动释放内存
go开发环境配置
基础语法
示例代码
package main
import (
"fmt"
)
func main() {
fmt.Println("hello word")
}
go语言以main函数作为程序入口函数
fmt主要用于输入输出操作
编译&运行
运行指令
go run path
编译指令
go build path
会编译生成可运行文件通过./filename运行程序
变量
go中变量的声明可以使用var关键字加变量名进行声明,go会根据变量值自动匹配变量类型
变量声明
var variableName = value
var variableName typeName
var variableName1,variableName2 typeName = value1,calue2
variableName := typeName(value)
常量声明
const variableName = value
const variableName tepeName = value
示例代码
package main
import (
"fmt"
"math"
)
func main() {
var a = "init"
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)
fmt.Println(g)
const s string = "const"
const h = 1024
const i = 4e7 / h
fmt.Println(s, h, i, math.Sin(h), math.Sin(i)) // Sin()为正弦函数
}
运行结果
分支结构之if-else
go语言的if语句与python类似,可以声明局部变量和进行表达式的运算
示例代码
package main
import (
"fmt"
)
func main() {
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
if 8%4 == 0 {
fmt.Println("8 is divisible by 4")
}
if num := 9; num < 0 { // 局部变量声明
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
}
运行结果
分支结构之switch
go语言的分支语句与c语言类似,但与c语言不同的是,go的case分支在结束时不需要使用break来结束case分支,则会自动跳出switch分支
并且go语言的switch语句使用也更加丰富,可以进行bool判断等
示例代码
package main
import (
"fmt"
)
func main() {
a := 2
switch a {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3, 4:
fmt.Println("three four")
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")
}
}
运行结果
循环for
go语言只有一种循环结构,就是for循环
并且go语言有多种for语法格式,可以不带参数,也可以像c语言for循环那样
示例代码
package main
import (
"fmt"
)
func main() {
i := 1
for {
fmt.Println("loop")
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 + 3
}
}
运行结果
数组
go语言数组与C语言类型,可以通过下标的方式访问数组元素,也可以创建多维数组
格式
var variableName [num1][num2]...typeName
示例代码
package main
import (
"fmt"
)
func main() {
var a [5]int
a[4] = 100
fmt.Println(a[4], len(a))
b := [5]int{1, 2, 3, 4, 5}
fmt.Println(b)
var twoD [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
twoD[i][j] = i + j
}
}
fmt.Println("2d: ", twoD)
}
运行结果
切片
切片就像C++中的动态数组一样,数组的大小不是固定不变的,可以进行动态的添加和删除元素
可以使用make函数创建切片,也可以像python那样对数组进行切片操作
示例代码
package main
import (
"fmt"
)
func main() {
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[2])
fmt.Println("len:", len(s))
s = append(s, "d") // 尾部添加
s = append(s, "e", "f")
fmt.Println(s)
c := make([]string, len(s))
copy(c, s)
fmt.Println(c)
fmt.Println(s[2:5])
fmt.Println(s[:5])
fmt.Println(s[2:])
good := []string{"g", "o", "o", "d"}
fmt.Println(good)
}
运行结果
map
go语言的map与c++的map容器 python的字典类似,都是对数据进行键值对的存储结构
map结构要通过make函数创建,通过delete函数删除map中的指定元素
示例代码
package main
import (
"fmt"
)
func main() {
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m)
fmt.Println(len(m))
fmt.Println(m["one"])
fmt.Println(m["unknow"])
r, ok := m["unknow"] // 返回m中"unknow"对应的值,如果存在则ok为true否则为false
fmt.Println(r, ok)
delete(m, "one") // 删除map中one对应的元素
m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
}
运行结果
函数
go语言函数的声明格式
func funName(形参变量名 typeName, ...) (返回值列表) {
return 返回值
}
go语言函数可以返回多个返回值,通常用多个返回值进行函数操作状态返回
示例代码
package main
import (
"fmt"
)
func add(a int, b int) int {
return a + b
}
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
func main() {
res := add(1, 2)
fmt.Println(res)
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok)
}
运行结果
指针
go语言内也存在指针的操作,但go语言的指针多数用于进行函数的传参
指针格式
variableName *typeName
示例代码
package main
import (
"fmt"
)
func add2(n int) {
n += 2
}
func add2ptr(n *int) {
*n += 2
}
func main() {
n := 5
add2(n)
fmt.Println(n)
add2ptr(&n)
fmt.Println(n)
}
运行结果
结构体
go语言与其他语言一样,也支持用户定义自己的变量类型,定义自己类型的属性和方法
格式
type variableName struct {
...
}
示例代码
package main
import (
"fmt"
)
type user struct {
name string
passwrd string
}
func checkPassword(u user, password string) bool {
return u.passwrd == password
}
func checkPassword2(u *user, password string) bool {
return u.passwrd == password
}
func main() {
a := user{name: "wang", passwrd: "1234"}
b := user{"wang", "1234"}
c := user{name: "wang"}
c.passwrd = "1234"
var d user
d.name = "wang"
d.passwrd = "1234"
fmt.Println(a, b, c, d)
fmt.Println(checkPassword(a, "haha"))
fmt.Println(checkPassword2(&a, "haha"))
}
运行结果
结构体方法
结构体方法就是结构体特有的函数,go语言中结构体方法不用在结构体中声明
格式
func (variableName structName) funName(形参变量名 typeName, ...) (返回值列表) {
...
}
示例代码
package main
import (
"fmt"
)
type user struct {
name string
passwrd string
}
func main() {
a := user{name: "wang", passwrd: "1234"}
fmt.Println(a.fCheckPassword("haha"))
a.resetPassword("haha")
fmt.Println(a)
}
func (u user) fCheckPassword(password string) bool {
return u.passwrd == password
}
func (u *user) resetPassword(password string) {
u.passwrd = password
}
运行结果
错误处理
go语言的错误处理基于errors静态库里的函数得以实现,一部分基于函数可以返回多个返回值的前提下更好的进行使用
示例代码
package main
import (
"errors"
"fmt"
"math"
"time"
)
type user struct {
name string
passwrd 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") // new 创建errors防止函数返回释放局部变量
}
func main() {
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name)
if u, err := findUser([]user{{"wang", "1024"}}, "zhang"); err != nil {
fmt.Println(err)
return
} else {
fmt.Println(u.name)
}
}
运行结果
字符串操作
strings头文件中也定义了很多好用的方法函数,用于对字符串进行操作
示例代码
package main
import (
"errors"
"fmt"
"math"
"strings"
"time"
)
func main() {
a := "hello"
fmt.Println(strings.Contains(a, "ll")) // 返回字符串是否含有该子串
fmt.Println(strings.Count(a, "l")) // 返回字符串中指定字符的个数
fmt.Println(strings.HasPrefix(a, "he")) // 判断字符串是否以指定字符或字符串开头
fmt.Println(strings.HasSuffix(a, "llo")) // 判断字符串是否以指定字符或字符串结尾
fmt.Println(strings.Index(a, "ll")) // 返回子串在字符串中的索引,存在则返回子串的起始位置否则返回-1
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // 拼接字符串
fmt.Println(strings.Repeat(a, 2)) // 按指定次数,重复字符串,但不会改变原有的字符串
fmt.Println(strings.Replace(a, "e", "E", -1)) // 按指定字符替换指定字符,最后一个参数为字符替换次数限制,-1则表示没有限制
fmt.Println(strings.Split("a-b-c", "-")) // 按指定字符对字符串进行分割
fmt.Println(strings.ToLower(a)) // 把字符串中大写字符替换为小写
fmt.Println(strings.ToUpper(a)) // 把字符串中小写字符替换为大写
fmt.Println(len(a))
b := "你好"
fmt.Println(len(b))
}
运行结果
字符串格式化
go也可以像c语言那样进行格式化输入输出,支持c语言的格式化操作符,也有新增的操作符%v可以对任意类型的数据进行输出
示例代码
package main
import (
"errors"
"fmt"
"math"
"strings"
"time"
)
type point struct {
x, y int
}
func main() {
s := "hello"
n := 123
p := point{1, 2}
fmt.Println(s, n)
fmt.Println(p)
fmt.Printf("s=%v\n", s)
fmt.Printf("n=%v\n", n)
fmt.Printf("p=%v\n", p)
fmt.Printf("p=%+v\n", p) // 输出值对应的变量
fmt.Printf("p=%#v\n", p) // 输出更详细的信息
f := 3.1415926
fmt.Println(f)
fmt.Printf("%.2f\n", f)
}
运行结果
json处理
json为网络数据传输的一种格式,go语言支持这种格式的解析
json结构体要求各变量名开头字母大写
示例代码
package main
import (
"encoding/json"
"errors"
"fmt"
"math"
"strings"
"time"
)
type userInfo struct {
Name string
Age int `json:"age"`
Hobby []string
}
func main() {
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Go", "type"}}
buf, err := json.Marshal(a) //对json数据进行编码
if err != nil {
panic(err) //结束程序运行
}
fmt.Println(buf)
fmt.Println(string(buf))
buf, err = json.MarshalIndent(a, "", "\t") // 对json数据进行缩进格式存储
if err != nil {
panic(err)
}
fmt.Println(string(buf))
var b userInfo
err = json.Unmarshal(buf, &b) //将json字符串转换为json结构体
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", b)
}
运行结果
时间处理
go语言也提供了一套完整的时间系统,用于时间方面的操作
示例代码
package main
import (
"encoding/json"
"errors"
"fmt"
"math"
"strings"
"time"
)
func main() {
now := time.Now() // 获取当前时间
fmt.Println(now)
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)
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute())
fmt.Println(t.Format("2006-01-02 15:04:05")) // 格式化输出时间,参数为输出格式 2006-01-02 15:04:05为特定的时间格式化
diff := t2.Sub(t) // 计算两个时间的相差值
fmt.Println(diff)
fmt.Println(diff.Minutes()/*分钟格式输出*/, diff.Seconds()/*秒格式输出*/)
t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36") // 解析格式化字符串为时间,第一个参数为样式也是固定为2006-01-02 15:04:05
if err != nil {
panic(err)
}
fmt.Println(t3 == t)
fmt.Println(now.Unix()) // 返回自1970-1-1日起到now代表时间以来的秒数
}
运行结果
数字解析
go语言也可以进行字符串转换为数字,数字转换为字符串的操作
示例代码
package main
import (
"encoding/json"
"errors"
"fmt"
"math"
"strconv"
"strings"
"time"
)
func main() {
f, _ := strconv.ParseFloat("1.235", 64)
fmt.Println(f)
n, _ := strconv.ParseInt("111", 10, 64)
fmt.Println(n)
n, _ = strconv.ParseInt("0x1000", 0, 64) // 第二个参数可以设置进制,0则会自动匹配
fmt.Println(n)
n2, _ := strconv.Atoi("123")
fmt.Println(n2)
n2, err := strconv.Atoi("AAA")
fmt.Println(n2, err)
}
运行结果
进程信息
go也提供函数对当前进程的信息进行输出
示例代码
package main
import (
"encoding/json"
"errors"
"fmt"
"math"
"os"
"os/exec"
"strconv"
"strings"
"time"
)
func main() {
fmt.Println(os.Args)
fmt.Println(os.Getenv("PATH"))
fmt.Println(os.Setenv("AA", "BB"))
buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
if err != nil {
panic(err)
}
fmt.Println(string(buf))
}
运行结果
到这里go语言的基础语法部分就介绍完了