首页 > 其他分享 >【一文入门】Go语言常用语法和案例

【一文入门】Go语言常用语法和案例

时间:2025-01-08 11:57:41浏览次数:3  
标签:func 入门 fmt 语法 Println context Go import main

简介

Go语言(Golang)作为一门现代编程语言,以其简洁、并发性强、编译速度快而备受欢迎。它由谷歌开发,旨在解决大型软件项目中的常见问题。对于初学者和有经验的开发者来说,Go语言提供了一套直观的语法和强大的工具集,可以高效地构建可靠的软件解决方案。

本篇文章旨在为读者提供一个详细的入门指南,涵盖Go语言的常用语法和实用案例。通过对变量声明、数据类型、控制结构、函数、结构体、接口、并发编程等核心概念的讲解,以及具体代码示例的展示,读者将能够迅速掌握Go语言的基础知识和进阶技巧。

此外,文章将深入探讨Go语言中独特的context包的应用,帮助读者理解如何在并发程序中高效地控制Goroutine的生命周期和资源管理。

无论您是刚开始探索Go语言的新手,还是希望深化理解的经验开发者,本篇文章都将为您提供有价值的参考资料,帮助您在Go语言的学习和实践中更进一步。

环境安装

Windows上自动安装 Go 脚本

基础语法

1. 变量声明与赋值

Go 支持多种方式声明和赋值变量。

package main

import "fmt"

func main() {
	// 声明并初始化变量
	var a int = 10
	var b = 20
	c := 30

	// 打印变量值
	fmt.Println(a, b, c)
}

2. 常量

常量的值在编译时确定,不能在运行时改变。

package main

import "fmt"

func main() {
	const Pi = 3.14
	fmt.Println("Pi:", Pi)
}

3. 数据类型

Go 提供多种内置数据类型,包括整数、浮点数、布尔值、字符串等。

package main

import "fmt"

func main() {
	var i int = 42
	var f float64 = 3.14
	var b bool = true
	var s string = "Hello, Go!"

	fmt.Println(i, f, b, s)
}

4. 数组与切片

数组是固定长度的,而切片是动态的,可以增长和收缩。

package main

import "fmt"

func main() {
	// 数组
	arr := [3]int{1, 2, 3}
	fmt.Println("Array:", arr)

	// 切片
	slice := []int{4, 5, 6}
	slice = append(slice, 7)
	fmt.Println("Slice:", slice)
}

5. 映射(Map)

映射是一种键值对数据结构。

package main

import "fmt"

func main() {
	// 创建映射
	m := map[string]int{"Alice": 25, "Bob": 30}
	m["Charlie"] = 35

	// 访问映射
	fmt.Println("Age of Alice:", m["Alice"])
}

6. 控制结构

Go 提供了多种控制结构,包括 ifforswitch 等。

package main

import "fmt"

func main() {
	// if 语句
	x := 10
	if x > 0 {
		fmt.Println("x is positive")
	}

	// for 循环
	for i := 0; i < 5; i++ {
		fmt.Println(i)
	}

	// switch 语句
	day := "Monday"
	switch day {
	case "Monday":
		fmt.Println("Start of the work week")
	case "Friday":
		fmt.Println("End of the work week")
	default:
		fmt.Println("Midweek")
	}
}

7. 函数

Go 支持函数的定义和调用,包括匿名函数和闭包。

package main

import "fmt"

// 定义函数
func add(x, y int) int {
	return x + y
}

func main() {
	// 调用函数
	sum := add(3, 4)
	fmt.Println("Sum:", sum)

	// 匿名函数
	func(message string) {
		fmt.Println(message)
	}("Hello from anonymous function")
}

8. 结构体

结构体是 Go 中的复合数据类型。

package main

import "fmt"

// 定义结构体
type Person struct {
	Name string
	Age  int
}

func main() {
	// 创建结构体实例
	p := Person{Name: "Alice", Age: 25}

	// 访问结构体字段
	fmt.Println("Name:", p.Name)
	fmt.Println("Age:", p.Age)
}

9. 接口

接口定义了类型的行为。

package main

import "fmt"

// 定义接口
type Speaker interface {
	Speak() string
}

// 实现接口的结构体
type Dog struct{}

func (d Dog) Speak() string {
	return "Woof!"
}

func main() {
	var s Speaker = Dog{}
	fmt.Println(s.Speak())
}

10. 并发

Go 使用 Goroutines 和通道(Channels)来实现并发。

package main

import (
	"fmt"
	"time"
)

// Goroutine 示例
func say(s string) {
	for i := 0; i < 3; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	go say("world")
	say("hello")
}

进阶语法

Go 语言不仅提供了简单易用的基础语法,还包含了一些高级特性和进阶语法,适用于更复杂的编程需求。以下是一些 Go 语言的进阶语法和相应的代码示例:

1. 空接口与类型断言

空接口 interface{} 可以表示任何类型,而类型断言用于获取接口的具体类型。

package main

import "fmt"

func describe(i interface{}) {
	fmt.Printf("Value: %v, Type: %T\n", i, i)
}

func main() {
	var i interface{} = "Hello, Go!"

	// 类型断言
	if str, ok := i.(string); ok {
		fmt.Println("String value:", str)
	} else {
		fmt.Println("Not a string")
	}

	describe(i)
}

2. 反射

反射用于在运行时检查类型和变量。

package main

import (
	"fmt"
	"reflect"
)

func main() {
	var x float64 = 3.14

	// 获取反射类型对象
	v := reflect.ValueOf(x)

	// 类型检查
	fmt.Println("Type:", v.Type())
	fmt.Println("Kind:", v.Kind())

	// 修改值
	v = reflect.ValueOf(&x).Elem()
	v.SetFloat(4.2)

	fmt.Println("Updated value:", x)
}

3. 方法集与接口

方法集决定了一个类型是否实现了某个接口。

package main

import "fmt"

// 定义接口
type Shape interface {
	Area() float64
}

// 定义结构体
type Circle struct {
	Radius float64
}

// 为 Circle 定义方法
func (c Circle) Area() float64 {
	return 3.14 * c.Radius * c.Radius
}

func printArea(s Shape) {
	fmt.Println("Area:", s.Area())
}

func main() {
	c := Circle{Radius: 5}
	printArea(c)
}

4. Channel 的高级用法

使用 select 语句进行多路复用。

package main

import (
	"fmt"
	"time"
)

func main() {
	ch1 := make(chan string)
	ch2 := make(chan string)

	go func() {
		time.Sleep(1 * time.Second)
		ch1 <- "from ch1"
	}()

	go func() {
		time.Sleep(2 * time.Second)
		ch2 <- "from ch2"
	}()

	for i := 0; i < 2; i++ {
		select {
		case msg1 := <-ch1:
			fmt.Println(msg1)
		case msg2 := <-ch2:
			fmt.Println(msg2)
		}
	}
}

5. 并发安全与 sync

使用互斥锁(sync.Mutex)保护共享资源。

package main

import (
	"fmt"
	"sync"
)

var (
	counter int
	lock    sync.Mutex
)

func increment(wg *sync.WaitGroup) {
	defer wg.Done()
	lock.Lock()
	counter++
	lock.Unlock()
}

func main() {
	var wg sync.WaitGroup

	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go increment(&wg)
	}

	wg.Wait()
	fmt.Println("Counter:", counter)
}

6. 延迟执行 defer

defer 用于确保函数退出前执行特定代码,常用于资源释放。

package main

import "fmt"

func main() {
	fmt.Println("Start")
	defer fmt.Println("Deferred execution")
	fmt.Println("End")
}

7. panicrecover

panic 用于异常处理,recover 用于捕获异常。

package main

import "fmt"

func riskyFunction() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered from panic:", r)
		}
	}()
	panic("A severe error occurred")
}

func main() {
	fmt.Println("Before risky function")
	riskyFunction()
	fmt.Println("After risky function")
}

8. 自定义错误类型

实现 error 接口来自定义错误类型。

package main

import (
	"fmt"
)

// 自定义错误类型
type MyError struct {
	Msg string
}

func (e *MyError) Error() string {
	return e.Msg
}

func riskyFunction() error {
	return &MyError{Msg: "Something went wrong"}
}

func main() {
	err := riskyFunction()
	if err != nil {
		fmt.Println("Error occurred:", err)
	}
}

Context常见用法

在 Go 语言中,context 包用于在 Goroutine 之间传递请求范围的值、取消信号和 deadline。它是编写并发程序的一个重要组成部分,尤其是在处理请求时。以下是一些与 context 相关的常用语法和操作,以及相应的代码示例:

1. 创建 context

创建一个根 context 通常使用 context.Background()context.TODO()

package main

import (
	"context"
	"fmt"
)

func main() {
	// 创建根 context
	ctx := context.Background()
	// 或者使用 ctx := context.TODO()

	fmt.Println("Context:", ctx)
}

2. WithCancel

context.WithCancel 创建一个可取消的子 context。当调用返回的取消函数时,子 context 会发送取消信号。

package main

import (
	"context"
	"fmt"
	"time"
)

func main() {
	// 创建一个可取消的 context
	ctx, cancel := context.WithCancel(context.Background())

	go func() {
		// 模拟工作
		time.Sleep(2 * time.Second)
		cancel() // 发送取消信号
	}()

	select {
	case <-ctx.Done():
		fmt.Println("Context canceled:", ctx.Err())
	}
}

3. WithTimeout

context.WithTimeout 创建一个包含超时的子 context,当超时时间到达时,context 会自动取消。

package main

import (
	"context"
	"fmt"
	"time"
)

func main() {
	// 创建一个带超时的 context
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel() // 确保在操作完成后调用取消以释放资源

	select {
	case <-time.After(3 * time.Second):
		fmt.Println("Operation completed")
	case <-ctx.Done():
		fmt.Println("Context timeout:", ctx.Err())
	}
}

4. WithDeadline

context.WithDeadline 类似于 WithTimeout,但它允许你指定一个具体的截止时间。

package main

import (
	"context"
	"fmt"
	"time"
)

func main() {
	// 设置一个绝对的截止时间
	deadline := time.Now().Add(2 * time.Second)
	ctx, cancel := context.WithDeadline(context.Background(), deadline)
	defer cancel()

	select {
	case <-time.After(3 * time.Second):
		fmt.Println("Operation completed")
	case <-ctx.Done():
		fmt.Println("Context deadline exceeded:", ctx.Err())
	}
}

5. WithValue

context.WithValue 用于在 context 中存储键值对。它可以在不支持直接传递参数的情况下在不同的 Goroutine 间传递值。

package main

import (
	"context"
	"fmt"
)

// 定义一个键类型以避免键冲突
type ctxKey string

func main() {
	k := ctxKey("userID")
	ctx := context.WithValue(context.Background(), k, 42)

	// 获取存储在 context 中的值
	if v, ok := ctx.Value(k).(int); ok {
		fmt.Println("UserID:", v)
	} else {
		fmt.Println("UserID not found")
	}
}

6. 使用 context 进行并发控制

在并发程序中,context 可以用于控制 Goroutine 的生命周期。

package main

import (
	"context"
	"fmt"
	"time"
)

func worker(ctx context.Context, id int) {
	for {
		select {
		case <-ctx.Done():
			fmt.Printf("Worker %d exiting\n", id)
			return
		default:
			fmt.Printf("Worker %d working\n", id)
			time.Sleep(500 * time.Millisecond)
		}
	}
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	for i := 0; i < 3; i++ {
		go worker(ctx, i)
	}

	time.Sleep(2 * time.Second)
	cancel()
	time.Sleep(1 * time.Second) // 等待 Goroutine 完成
}

总结

  • context.Backgroundcontext.TODO: 用于初始化 context
  • WithCancel: 创建一个可取消的 context
  • WithTimeoutWithDeadline: 创建一个有超时或截止时间的 context
  • WithValue: 在 context 中传递键值对。
  • 并发控制: 使用 context 可以有效控制并发程序中 Goroutine 的生命周期。

标签:func,入门,fmt,语法,Println,context,Go,import,main
From: https://blog.csdn.net/sinat_41883985/article/details/144612344

相关文章

  • 基于Django+Vue的白酒数据推荐系统
    一、前言......
  • 基于Django+Vue的期货程序化交易系统
    一、前言......
  • CAN总线入门指南:从原理到实践
    1CAN通信基础概述CAN(ControllerAreaNetwork)是一种串行通信协议,由德国BOSCH公司于1986年专门为汽车分布式控制系统开发。它最初的目标是减少汽车中的线束数量,降低整车重量和成本。经过30多年的发展,CAN已经成为汽车电子领域的标准总线,并广泛应用于工业自动化、医疗设备、智能......
  • AI 与 Mermaid 使用教程之流程图 - 从入门到精通
    本文由 Mermaid中文文档 整理而来,并且它同时提供了一个Mermaid在线编辑器,支持在线编辑与生成流程图。在文章的末尾我们将介绍如何使用AI来自动生成Mermaid流程图。Mermaid流程图-基本语法流程图由节点(几何形状)和边(箭头或线)组成。Mermaid代码定义了如何创建节点和边,并......
  • golang OpcUaClient
    实现功能packagemainimport("fmt""log""opcuaclient/util/plugin/client/opcclient""os""os/signal""syscall")funcmain(){OPCUATest()//监听操作系统信号,阻塞直到接收到信号......
  • 【Transformer】小白入门指南
    目录1、简介2、Transformer解决问题技术概览核心组成自注意力机制(Self-AttentionMechanism)多头注意力机制(Multi-HeadAttention)前馈神经网络(Feed-ForwardNeuralNetwork)位置编码(PositionalEncoding)残差连接与标准化框架认识1.输入输出2.Encoder3.Decoder4......
  • Go 语言与 Tesseract OCR 实现英文数字验证码识别
    Go语言本身不直接支持图像识别,但可以通过调用TesseractOCR引擎来进行图像识别。我们可以使用Go的tesseract包来实现这一功能。一、安装与配置安装TesseractOCR首先,你需要在系统中安装TesseractOCR。安装方法和前面一样:Ubuntu(Linux):bashsudoapt-getupdatesudo......
  • 在 GoRoute 中使用 NavigationBar
    前言在App中通常会把主要的几个页面放在下方icon,让使用者能够方便操作,这个元件在flutter中称为BottomNavigationBar。而GoRouter则是Flutter官方所提供的套件,可以用来整合整个专案的路由。当这两个功能整合在一起的时候,一个不小心呈现出来的效果就会差很多。准备:先创建一个......
  • 【Java从入门到放弃 之 final 关键字】
    final关键字final关键字final字段final函数列表中的参数final方法final类final关键字Java中里面有final这个关键字,这个关键字总体上是用来表达”不能被改变“这个意思的。我们使用这个关键字表达不能被改变,有两种使用场景,有三个使用位置。使用场景设计上......
  • django form使用
    示例代码:formfromdjangoimportformsfromdjango.confimportsettingsfromdjango.core.exceptionsimportValidationErrorfromdjango.core.validatorsimportRegexValidatorfromdjango_redisimportget_redis_connectionfromutils.encryptimportmd5fromuti......