Go语言
Go基础
Go语言特性
Go语言是由Google开发的一种静态类型、编译型语言,具有以下特点:
- 简洁高效:语法简洁,编译速度快
- 并发支持:内置goroutine和channel,原生支持并发
- 垃圾回收:自动内存管理
- 强类型:编译时类型检查
- 跨平台:支持多种操作系统和架构
基础语法
go
package main
import (
"fmt"
"net/http"
)
// 结构体定义
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
}
// 方法定义
func (u *User) GetFullInfo() string {
return fmt.Sprintf("ID: %d, Username: %s, Email: %s", u.ID, u.Username, u.Email)
}
// 接口定义
type UserService interface {
GetUser(id int) (*User, error)
CreateUser(user *User) error
}
func main() {
fmt.Println("Hello, Go!")
}
Web框架
Gin框架
Gin是一个高性能的HTTP Web框架。
基础使用
go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
}
func main() {
r := gin.Default()
// 中间件
r.Use(gin.Logger())
r.Use(gin.Recovery())
// 路由
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
// 用户相关路由
users := r.Group("/api/users")
{
users.GET("", getUsers)
users.GET("/:id", getUser)
users.POST("", createUser)
users.PUT("/:id", updateUser)
users.DELETE("/:id", deleteUser)
}
r.Run(":8080")
}
func getUsers(c *gin.Context) {
users := []User{
{ID: 1, Username: "john", Email: "[email protected]"},
{ID: 2, Username: "jane", Email: "[email protected]"},
}
c.JSON(http.StatusOK, users)
}
func getUser(c *gin.Context) {
id := c.Param("id")
// 这里应该从数据库查询
user := User{ID: 1, Username: "john", Email: "[email protected]"}
c.JSON(http.StatusOK, user)
}
func createUser(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 这里应该保存到数据库
c.JSON(http.StatusCreated, user)
}
func updateUser(c *gin.Context) {
id := c.Param("id")
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 这里应该更新数据库
c.JSON(http.StatusOK, user)
}
func deleteUser(c *gin.Context) {
id := c.Param("id")
// 这里应该从数据库删除
c.JSON(http.StatusOK, gin.H{"message": "User deleted"})
}
Echo框架
Echo是一个高性能、可扩展的Go Web框架。
go
package main
import (
"github.com/labstack/echo/v4"
"net/http"
)
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
}
func main() {
e := echo.New()
// 中间件
e.Use(middleware.Logger())
e.Use(middleware.Recover())
// 路由
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, Echo!")
})
// API路由
api := e.Group("/api")
api.GET("/users", getUsers)
api.POST("/users", createUser)
e.Start(":8080")
}
func getUsers(c echo.Context) error {
users := []User{
{ID: 1, Username: "john", Email: "[email protected]"},
}
return c.JSON(http.StatusOK, users)
}
func createUser(c echo.Context) error {
user := new(User)
if err := c.Bind(user); err != nil {
return err
}
return c.JSON(http.StatusCreated, user)
}
数据库操作
GORM
GORM是Go语言最流行的ORM框架。
go
package main
import (
"gorm.io/gorm"
"gorm.io/driver/mysql"
"time"
)
type User struct {
ID uint `gorm:"primaryKey"`
Username string `gorm:"uniqueIndex;not null"`
Email string `gorm:"uniqueIndex;not null"`
CreatedAt time.Time
UpdatedAt time.Time
}
func main() {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 自动迁移
db.AutoMigrate(&User{})
// 创建用户
user := User{Username: "john", Email: "[email protected]"}
db.Create(&user)
// 查询用户
var foundUser User
db.First(&foundUser, "username = ?", "john")
// 更新用户
db.Model(&foundUser).Update("Email", "[email protected]")
// 删除用户
db.Delete(&foundUser, foundUser.ID)
}
原生SQL
go
package main
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "user:password@/dbname")
if err != nil {
panic(err)
}
defer db.Close()
// 查询
rows, err := db.Query("SELECT id, username, email FROM users")
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
var id int
var username, email string
err := rows.Scan(&id, &username, &email)
if err != nil {
panic(err)
}
fmt.Printf("ID: %d, Username: %s, Email: %s\n", id, username, email)
}
// 插入
result, err := db.Exec("INSERT INTO users(username, email) VALUES(?, ?)", "john", "[email protected]")
if err != nil {
panic(err)
}
lastID, err := result.LastInsertId()
if err != nil {
panic(err)
}
fmt.Printf("插入的用户ID: %d\n", lastID)
}
并发编程
Goroutine
go
package main
import (
"fmt"
"time"
)
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("worker %d processing job %d\n", id, j)
time.Sleep(time.Second)
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// 启动3个worker
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// 发送9个任务
for j := 1; j <= 9; j++ {
jobs <- j
}
close(jobs)
// 收集结果
for a := 1; a <= 9; a++ {
<-results
}
}
Channel
go
package main
import (
"fmt"
"time"
)
func producer(ch chan<- int) {
for i := 0; i < 5; i++ {
ch <- i
time.Sleep(time.Millisecond * 500)
}
close(ch)
}
func consumer(ch <-chan int) {
for v := range ch {
fmt.Printf("Received: %d\n", v)
}
}
func main() {
ch := make(chan int, 2)
go producer(ch)
go consumer(ch)
time.Sleep(time.Second * 3)
}
Select语句
go
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(time.Second)
ch1 <- "one"
}()
go func() {
time.Sleep(time.Second * 2)
ch2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("received", msg1)
case msg2 := <-ch2:
fmt.Println("received", msg2)
case <-time.After(time.Second * 3):
fmt.Println("timeout")
}
}
}
错误处理
错误处理模式
go
package main
import (
"errors"
"fmt"
)
type User struct {
ID int
Username string
Email string
}
type UserService struct {
users map[int]*User
}
func NewUserService() *UserService {
return &UserService{
users: make(map[int]*User),
}
}
func (s *UserService) GetUser(id int) (*User, error) {
user, exists := s.users[id]
if !exists {
return nil, errors.New("user not found")
}
return user, nil
}
func (s *UserService) CreateUser(user *User) error {
if user.Username == "" {
return errors.New("username cannot be empty")
}
if user.Email == "" {
return errors.New("email cannot be empty")
}
s.users[user.ID] = user
return nil
}
func main() {
service := NewUserService()
// 创建用户
user := &User{ID: 1, Username: "john", Email: "[email protected]"}
if err := service.CreateUser(user); err != nil {
fmt.Printf("Error creating user: %v\n", err)
return
}
// 获取用户
foundUser, err := service.GetUser(1)
if err != nil {
fmt.Printf("Error getting user: %v\n", err)
return
}
fmt.Printf("Found user: %+v\n", foundUser)
}
测试
单元测试
go
package main
import (
"testing"
)
func TestAdd(t *testing.T) {
result := Add(2, 3)
expected := 5
if result != expected {
t.Errorf("Add(2, 3) = %d; expected %d", result, expected)
}
}
func TestAddTable(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 1, 2, 3},
{"negative", -1, -2, -3},
{"zero", 0, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Add(%d, %d) = %d; expected %d", tt.a, tt.b, result, tt.expected)
}
})
}
}
func Add(a, b int) int {
return a + b
}
HTTP测试
go
package main
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
)
func TestGetUsers(t *testing.T) {
gin.SetMode(gin.TestMode)
r := gin.New()
r.GET("/api/users", getUsers)
req, _ := http.NewRequest("GET", "/api/users", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
}
部署
Docker
dockerfile
FROM golang:1.19-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main .
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]
交叉编译
bash
# 编译Linux版本
GOOS=linux GOARCH=amd64 go build -o app-linux main.go
# 编译Windows版本
GOOS=windows GOARCH=amd64 go build -o app-windows.exe main.go
# 编译macOS版本
GOOS=darwin GOARCH=amd64 go build -o app-darwin main.go
性能优化
基准测试
go
package main
import (
"testing"
)
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(1, 2)
}
}
func BenchmarkStringConcat(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = "hello" + " " + "world"
}
}
func BenchmarkStringBuilder(b *testing.B) {
for i := 0; i < b.N; i++ {
var builder strings.Builder
builder.WriteString("hello")
builder.WriteString(" ")
builder.WriteString("world")
_ = builder.String()
}
}
内存优化
go
package main
import (
"sync"
"time"
)
// 对象池
var userPool = sync.Pool{
New: func() interface{} {
return &User{}
},
}
func getUserFromPool() *User {
return userPool.Get().(*User)
}
func putUserToPool(user *User) {
user.ID = 0
user.Username = ""
user.Email = ""
userPool.Put(user)
}
最佳实践
项目结构
myproject/
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ ├── handler/
│ ├── service/
│ ├── repository/
│ └── model/
├── pkg/
│ ├── database/
│ └── middleware/
├── configs/
├── scripts/
├── go.mod
└── go.sum
配置管理
go
package main
import (
"github.com/spf13/viper"
)
type Config struct {
Server ServerConfig `mapstructure:"server"`
Database DatabaseConfig `mapstructure:"database"`
}
type ServerConfig struct {
Port int `mapstructure:"port"`
}
type DatabaseConfig struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Database string `mapstructure:"database"`
}
func LoadConfig() (*Config, error) {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil {
return nil, err
}
var config Config
if err := viper.Unmarshal(&config); err != nil {
return nil, err
}
return &config, nil
}
Go语言以其简洁的语法、强大的并发支持和优秀的性能,在微服务、云原生应用等领域得到广泛应用。