GoLang语言入门
简介
GoLang(也被称为Go)是一门由Google开发的开源编程语言。它在许多方面都非常优秀,具有以下特点:
- 高性能、高并发:Go语言通过轻量级的线程(goroutine)和通信原语(channel)实现高效的并发编程,适合构建高性能的分布式系统。
- 语法简单、学习曲线平缓:Go的语法设计简洁,易于理解,没有繁琐的特性和复杂的用法,初学者可以快速上手。
- 丰富的标准库:Go拥有一个强大的标准库,涵盖了网络、文件处理、加密、文本处理等多个领域,开发者可以直接使用这些库来提高开发效率。
- 完善的工具链:Go提供了一套全面的工具,包括格式化工具、测试工具、性能分析工具等,方便开发者进行代码管理和优化。
- 静态链接:Go语言的编译器将所有依赖打包为一个可执行文件,简化了部署和交付过程。
- 快速编译:Go的编译速度很快,对于大型项目也能快速完成编译,提高了开发效率。
- 跨平台:Go可以在各种操作系统上运行,开发者可以在不同平台上编译和运行相同的代码。
- 垃圾回收:Go拥有自动内存管理,内置垃圾回收机制,开发者不需要手动管理内存,减少了出现内存泄漏的可能性。
基础语法
HelloWorld
package main
import "fmt"
func main() {
fmt.Println("HelloWorld!")
}
定义变量
Go语言中的基本数据类型包括:
- 布尔类型:bool
- 字符串类型:string
- 整数类型:int, int8, int16, int32, int64
- 无符号整数类型:uint, uint8, uint16, uint32, uint64, uintptr
- 字节类型:byte(uint8的别名)
- Unicode字符类型:rune(int32的别名)
- 浮点数类型:float32, float64
- 复数类型:complex64, complex128
package main
import "fmt"
func main() {
var a = 100 // 使用var关键字声明变量,编译器自动推断类型
fmt.Println("a =", a)
c := 'A' // 使用:=短变量声明,编译器自动推断类型
fmt.Println("c =", c)
var b float64 = 64.648 // 显式声明变量类型
fmt.Println("b =", b)
const name = "stacker" // 常量声明
fmt.Println("name =", name)
}
if - else流程控制语句
package main
import (
"fmt"
"math"
)
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
} else {
fmt.Printf("%g >= %g\n", v, lim)
}
// 这里开始就不能使用 v 了
return lim
}
func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 3, 20),
)
}
for循环
在Go语言中,for循环可以用于多种情况。
- 类似C语言中的for循环:
package main
import "fmt"
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
}
- 类似C语言中的while循环:
package main
import "fmt"
func main() {
sum := 1
for sum < 1000 {
sum += sum
}
fmt.Println(sum)
}
- 无限循环(类似C语言中的While(1)):
package main
func main() {
for {
// 循环体
}
}
switch分支结构
Go语言的switch语句与C、Java等语言有所不同。Go的switch默认是带有break的,即匹配到一个分支后会自动跳出switch,不会继续执行其他分支。如果需要贯穿多个分支,可以使用fallthrough关键字实现。
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Print("Go runs on ")
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.")
case "linux":
fmt.Println("Linux.")
default:
fmt.Printf("%s.\n", os)
}
}
数组
package main
import "fmt"
func main() {
var a [2]string
a[0] = "Hello"
a[1] = "World"
fmt.Println(a[0], a[1])
fmt.Println(a)
primes := [6]int{2, 3, 5, 7, 11, 13}
fmt.Println(primes)
}
切片*
切片是Go中重要的数据结构,可以看作是数组的一种引用。切片提供了对数组的动态访问,更加灵活和方便。
package main
import "fmt"
func main() {
primes := [6]int{2, 3, 5, 7, 11, 13}
var s []int = primes[1:4]
fmt.Println(s)
}
使用make函数创建切片:
package main
import "fmt"
func main() {
a := make([]int, 5)
printSlice("a", a)
b := make([]int, 0, 5)
printSlice("b", b)
c := b[:2]
printSlice("c", c)
d := c[2:5]
printSlice("d", d)
}
func printSlice(s string, x []int) {
fmt.Printf("%s len=%d cap=%d %v\n",
s, len(x), cap(x), x)
}
使用append函数向切片追加元素:
package main
import "fmt"
func main() {
var s []int
printSlice(s)
// 添加一个空切片
s = append(s, 0)
printSlice(s)
// 这个切片会按需增长
s = append(s, 1)
printSlice(s)
// 可以一次性添加多个元素
s = append(s, 2, 3, 4)
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
map
map是Go语言中的一种关联数据类型,也称为字典或哈希表。它由一系列键值对组成,每个键值对表示一个映射关系。
package main
import "fmt"
type Vertex struct {
Lat, Long float64
}
var m map[string]Vertex
func main() {
m = make(map[string]Vertex)
m["Bell Labs"] = Vertex{
40.68433, -74.39967,
}
fmt.Println(m["Bell Labs"])
}
range
range用于遍历数组、切片、字符串、map等数据结构。它返回索引和元素的值。
package main
import "fmt"
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
}
package main
import "fmt"
func main() {
pow := make([]int, 10)
for i := range pow {
pow[i] = 1 << uint(i) // == 2**i
}
for _, value := range pow {
fmt.Printf("%d\n", value)
}
}
函数
函数是Go中的基本组件之一,可以在函数中执行特定的任务并返回结果。Go语言支持多参数、多返回值和命名返回值。
package main
import "fmt"
func add(x int, y int) int {
return x + y
}
func main() {
fmt.Println(add(42, 13))
}
简化后的参数声明:
package main
import "fmt"
func add(x, y int) int {
return x + y
}
func main() {
fmt.Println(add(42, 13))
}
支持多返回值:
package main
import "fmt"
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := swap("hello", "world")
fmt.Println(a, b)
}
返回值可命名:
package main
import "fmt"
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
func main() {
fmt.Println(split(17))
}
指针
指针是一种特殊的数据类型,用于存储变量的内存地址。通过指针,可以直接访问变量的内存内容。
package main
import "fmt"
func main() {
i, j := 42, 2701
p := &i // 指向 i
fmt.Println(*p) // 通过指针读取 i 的值
*p = 21 // 通过指针设置 i 的值
fmt.Println(i) // 查看 i 的值
p = &j // 指向 j
*p = *p / 37 // 通过指针对 j 进行除法运算
fmt.Println(j) // 查看 j 的值
}
结构体
结构体是一种复合数据类型,可以用来表示一组相关字段的集合。
package main
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
fmt.Println(Vertex{1, 2})
}
结构体方法
在Go语言中,结构体可以定义方法,方法是一种特殊的函数,与结构体关联。
package main
import "fmt"
type User struct {
Username string
Password string
}
// 普通方法
func resetPassword(u User, password string) {
u.Password = password
}
// 结构体方法
func (u *User) resetPassword(password string) {
u.Password = password
}
func main() {
user := User{
Username: "john",
Password: "123456",
}
// 调用普通方法
resetPassword(user, "new_password")
fmt.Println("普通方法修改后的密码:", user.Password)
// 调用结构体方法
user.resetPassword("new_password2")
fmt.Println("结构体方法修改后的密码:", user.Password)
}
错误处理
在Go中,错误是一种普遍的返回值类型,通常用于表示函数调用过程中发生的错误。可以使用errors.New()函数创建一个新的错误实例。
package main
import (
"errors"
"fmt"
)
func Hello(name string) (string, error) {
if name == "" {
return "", errors.New("empty name error!")
}
message := fmt.Sprintf("Hi, Hello %s", name)
return message, nil
}
字符串操作
Go语言提供了丰富的字符串操作函数,可以方便地进行字符串处理。
package main
import (
"fmt"
"strings"
)
func main() {
var str string = "golang golang"
// 字符串克隆
var tmpStr string = strings.Clone(str)
fmt.Println("str =", str, " tmpStr =", tmpStr)
// 字符串比较
if strings.Compare(str, tmpStr) == 0 {
fmt.Println("same!")
} else if strings.Compare(str, tmpStr) == 1 {
fmt.Println("str bigger")
} else { // strings.Compare(str, tmpStr) == -1
fmt.Println("str smaller")
}
// 字符串包含
if strings.Contains(str, "go") {
fmt.Println(str, " has go")
}
// 字符串计数
var counter int = strings.Count(str, "go")
fmt.Println("counter =", counter)
// 字符串索引 不存在返回-1
var index int = strings.Index(str, " ")
fmt.Println("index =", index)
}
JSON处理
Go语言内置了对JSON的支持,可以方便地进行JSON的序列化和反序列化。
package main
import (
"fmt"
"encoding/json"
)
type UserInfo struct {
Name string
Age int
}
func main() {
user := UserInfo{Name: "stackor", Age: 18}
// 序列化为JSON格式
buf, err := json.Marshal(user)
if err != nil {
panic(err)
}
fmt.Println(buf) // 输出二进制数据
fmt.Println(string(buf)) // 输出JSON字符串
// 反序列化JSON数据
var b UserInfo
err = json.Unmarshal(buf, &b)
if err != nil {
panic(err)
}
fmt.Printf("%#v", b)
}
时间处理
Go语言提供了时间相关的函数和结构体,可以方便地进行时间的表示和计算。
package main
import (
"fmt"
"time"
)
func main() {
nowTime := time.Now()
fmt.Println(nowTime) // 例如:2023-07-25 11:29:13.985157 +0800 CST m=+0.000144293
t := time.Date(2003, 11, 21, 2, 30, 30, 0, time.UTC)
fmt.Println(t)
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
fmt.Println(t.Format("2006-01-02 03:04:05"))
t2 := time.Date(2003, 11, 22, 3, 30, 30, 0, time.UTC)
diff := t2.Sub(t)
fmt.Println(diff) // 输出:25h0m0s
// 获取时间戳
fmt.Println(nowTime.Unix())
}
数字转换
在Go语言中,可以通过strconv包进行字符串和基本数据类型之间的转换。
package main
import (
"fmt"
"strconv"
)
func main() {
f, _ := strconv.ParseInt("100", 10, 64)
fmt.Println(f)
f, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(f)
t, _ := strconv.ParseFloat("12.1012", 64)
fmt.Println(t)
n1, _ := strconv.Atoi("123")
fmt.Println(n1)
n2, err := strconv.Atoi("AAA")
fmt.Println(n2, err)
}