Golang Math标准库 Golang
package main
import (
"fmt"
"math"
"math/rand"
"time"
)
func main(){
// Math
// math 标准库提供了常用的数学函数和常量,涵盖浮点运算、三角函数、指数运算、对数运算等,适用于科学计算、工程计算和其他需要数学支持的场景
// 主要功能分类
// 常量
// 提供数学相关的常量,如圆周率、最大/最小值等。
// 基础运算
// 提供平方根、绝对值、幂运算等基本数学运算。
// 三角函数
// 包括正弦、余弦、正切及其反函数。
// 对数与指数
// 包括自然对数、以 10 为底的对数、指数运算等。
// 舍入函数
// 提供向上取整、向下取整、四舍五入等功能。
// 数字和常量
// math.Pi 3.141592653589793 圆周率
// math.E 2.718281828459045 自然常数 e
// math.MaxFloat64 最大的 float64 值
// math.SmallestNonzeroFloat64 最小的非零 float64 值
// math.MaxInt64 最大的 int64 值
// math.MinInt64 最小的 int64 值
fmt.Println("math.Pi",math.Pi)
fmt.Println("math.E",math.E)
fmt.Println("math.MaxFloat64",math.MaxFloat64)
fmt.Println("math.MaxInt64",math.MaxInt64)
// 基础运算
// math.Abs(x) 返回 x 的绝对值 math.Abs(-5.5) → 5.5
// math.Sqrt(x) 返回 x 的平方根 math.Sqrt(16) → 4
// math.Pow(x, y) 返回 x 的 y 次幂 math.Pow(2, 3) → 8
// math.Mod(x, y) 返回 x 除以 y 的余数(浮点数) math.Mod(10, 3) → 1
// math.Ceil(x) 向上取整 math.Ceil(2.3) → 3
// math.Floor(x) 向下取整 math.Floor(2.7) → 2
// math.Round(x) 四舍五入 math.Round(2.5) → 3
// math.Trunc(x) 返回 x 的整数部分(去掉小数) math.Trunc(3.9) → 3
fmt.Println("math.Ceil",math.Ceil(6.5)) // 向上取整
fmt.Println("math.Floor",math.Floor(6.5)) // 向下取整
fmt.Println("math.Round",math.Round(6.5)) // 四舍五入
// 三角函数
// math.Sin(x) 返回 x 的正弦值 math.Sin(math.Pi/2) → 1
// math.Cos(x) 返回 x 的余弦值 math.Cos(math.Pi) → -1
// math.Tan(x) 返回 x 的正切值 math.Tan(math.Pi/4) → 1
// math.Asin(x) 返回 x 的反正弦值(弧度) math.Asin(1) → Pi/2
// math.Acos(x) 返回 x 的反余弦值(弧度) math.Acos(1) → 0
// math.Atan(x) 返回 x 的反正切值(弧度) math.Atan(1) → Pi/4
// 对数与指数
// math.Exp(x) 返回 e^x math.Exp(1) → 2.718281828459045
// math.Log(x) 返回 x 的自然对数 math.Log(math.E) → 1
// math.Log10(x) 返回 x 的以 10 为底的对数 math.Log10(100) → 2
// math.Log2(x) 返回 x 的以 2 为底的对数 math.Log2(8) → 3
// 比较函数
// math.Max(x, y) 返回 x 和 y 中的较大值 math.Max(10, 20) → 20
// math.Min(x, y) 返回 x 和 y 中的较小值 math.Min(10, 20) → 10
var numA float64 = 10
var numB float64 = 20
maxNum := math.Max(numA,numB) // 获取两个中较大值
fmt.Println(maxNum)
// 生成随机数
// 使用当前时间戳作为种子
rand.Seed(time.Now().UnixNano())
// 生成随机整数
fmt.Println("随机整数:", rand.Intn(100))
// 生成随机浮点数
fmt.Println("随机浮点数:", rand.Float64())
}
标签: Golang标准库
Golang fmt标准库 Golang
package main
import "fmt"
import "time"
type User struct {
Name string
Email string
Age int
}
func main(){
// fmt包介绍
// fmt 是一个用于格式化 I/O 的标准库包,提供了格式化字符串输出和输入的功能。
// fmt 包广泛用于打印日志、调试信息以及格式化字符串等场景
// 核心功能分类
// 格式化输出函数
// Print 系列:直接输出到标准输出。
// Fprint 系列:输出到指定的 io.Writer。
// Sprint 系列:将结果作为字符串返回。
// 格式化输入函数
// Scan 系列:从标准输入读取数据。
// Fscan 系列:从指定的 io.Reader 读取数据。
// Sscan 系列:从字符串中解析数据。
// 格式化字符串
// 使用格式化占位符实现自定义输出。
// 输出函数
// fmt.Print 直接输出内容,不自动换行。
// fmt.Println 输出内容,并在结尾自动换行。
// fmt.Printf 支持格式化输出,需提供格式化字符串(如 %d, %s)。
// fmt.Sprint 格式化内容并返回字符串,不输出。
// fmt.Sprintln 格式化内容,添加换行符后返回字符串。
// fmt.Sprintf 格式化内容并返回字符串,不输出。
name := "Alice"
age := 30
fmt.Print("Hello, ") // 不换行
fmt.Println("world!") // 换行
fmt.Printf("My name is %s and I am %d years old.\n", name, age)
result := fmt.Sprintf("Name: %s, Age: %d", name, age) // 返回字符串
fmt.Println(result)
// 输出复杂数据
user := User{Name: "Alice", Email: "alice@example.com", Age: 30}
fmt.Printf("Default: %v\n", user)
fmt.Printf("With field names: %+v\n", user)
fmt.Printf("Go syntax: %#v\n", user)
// 输出时间
fmt.Printf("Current time: %s\n", time.Now().Format("2006-01-02 15:04:05"))
// 输入函数
// fmt.Scan 从标准输入读取值,并赋值给提供的变量。
// fmt.Scanln 类似 Scan,但要求输入换行结束。
// fmt.Scanf 从标准输入按格式化字符串读取值。
// fmt.Fscan 从 io.Reader 中读取值,并赋值给提供的变量。
// fmt.Sscan 从字符串中解析值,并赋值给提供的变量。
var name1 string
var age1 int
fmt.Println("Enter your name and age:")
fmt.Scanln(&name1, &age1) // 从标准输入读取数据
fmt.Printf("Hello %s, you are %d years old.\n", name1, age1)
// 通用占位符
// %v 默认格式输出变量的值。
// %+v 输出结构体时,会包含字段名和值。
// %#v 输出变量的 Go 语法表示形式。
// %T 输出变量的类型。
// %% 输出 % 字符。
// 数字相关占位符
// %b 二进制表示。
// %c 对应的 Unicode 字符。
// %d 十进制表示。
// %o 八进制表示。
// %x 十六进制表示(小写字母)。
// %X 十六进制表示(大写字母)。
// %f 十进制浮点数表示(默认精度 6)。
// %e 科学计数法表示(小写 e)。
// %E 科学计数法表示(大写 E)。
// 字符串相关占位符
// %s 输出字符串或字节切片内容。
// %q 带双引号的字符串。
// %x 每个字节以两位十六进制表示(小写)。
// %X 每个字节以两位十六进制表示(大写)。
// %t 输出布尔值的 true 或 false。
}
标签: Golang标准库
Golang 并发编程sync包 Golang
package main
import (
"fmt"
"sync"
)
// sync包
func main(){
// Go 语言的 sync 包提供了用于同步的原语,主要用于多个 goroutine 之间的协调与同步。
// sync 包中有几个非常重要的同步工具,帮助你处理并发编程中的竞态条件、资源共享和执行顺序等问题
// sync.WaitGroup
// sync.WaitGroup 用于等待一组 goroutine 完成。它可以帮助你在多个 goroutine 执行完之后再继续执行后续的代码
// 用法:
// 调用 Add(n) 来设置等待的 goroutine 数量。
// 每个 goroutine 执行完后,调用 Done() 来通知 WaitGroup,表示一个 goroutine 完成了。
// Wait() 会阻塞,直到所有的 goroutine 都完成。
//示例
// func task(id int, wg *sync.WaitGroup) {
// defer wg.Done() // 标记 goroutine 完成
// fmt.Printf("任务 %d 开始\n", id)
// }
// func main() {
// var wg sync.WaitGroup
// // 启动多个 goroutine
// for i := 1; i <= 3; i++ {
// wg.Add(1) // 设置等待的 goroutine 数量
// go task(i, &wg)
// }
// wg.Wait() // 等待所有 goroutine 完成
// fmt.Println("所有任务完成")
// }
// sync.Mutex
// 互斥锁,用于保护临界区,确保同一时刻只有一个 goroutine 可以访问共享资源。它可以防止多个 goroutine 同时访问共享数据,从而避免数据竞态问题
// 用法:
// Lock():获取锁,如果锁已经被其他 goroutine 持有,当前 goroutine 会被阻塞,直到锁被释放。
// Unlock():释放锁,允许其他 goroutine 获取锁。
// var (
// mu sync.Mutex
// count int
// )
// func increment(wg *sync.WaitGroup) {
// defer wg.Done()
// mu.Lock() // 获取锁
// count++ // 访问共享数据
// mu.Unlock() // 释放锁
// }
// func main() {
// var wg sync.WaitGroup
// // 启动多个 goroutine 来并发地增加 count
// for i := 0; i < 5; i++ {
// wg.Add(1)
// go increment(&wg)
// }
// wg.Wait()
// fmt.Println("最终 count 值:", count)
// }
// sync.RWMutex
// 读写锁,它允许多个 goroutine 同时读取共享数据,但写入操作会阻塞所有其他读写操作。适用于读多写少的场景
// 用法:
// RLock():获取读锁,多个 goroutine 可以同时获取读锁。
// RUnlock():释放读锁。
// Lock():获取写锁,写锁会阻塞所有的读锁和写锁。
// Unlock():释放写锁。
// var (
// rwmu sync.RWMutex
// data int
// )
// func readData(wg *sync.WaitGroup) {
// defer wg.Done()
// rwmu.RLock() // 获取读锁
// fmt.Println("读取数据:", data)
// rwmu.RUnlock() // 释放读锁
// }
// func writeData(wg *sync.WaitGroup, value int) {
// defer wg.Done()
// rwmu.Lock() // 获取写锁
// data = value
// fmt.Println("写入数据:", data)
// rwmu.Unlock() // 释放写锁
// }
// func main() {
// var wg sync.WaitGroup
// // 启动多个 goroutine
// wg.Add(3)
// go readData(&wg)
// go writeData(&wg, 42)
// go readData(&wg)
// wg.Wait()
// }
// sync.Once
// 用于确保某个操作只执行一次,常用于初始化操作。无论多少次调用 Do(),该操作只会执行一次
// 用法:
// Do(f func()):执行传入的函数 f,如果该函数尚未执行过,它会执行一次。
// var once sync.Once
// func initOnce() {
// fmt.Println("初始化一次操作")
// }
// func main() {
// // 调用 Do,确保初始化操作只执行一次
// once.Do(initOnce)
// once.Do(initOnce) // 不会执行
// once.Do(initOnce) // 不会执行
// }
// sync/atomic 包
// 提供了原子操作,用于在并发环境中安全地操作基本数据类型。原子操作是不可分割的操作,保证在执行过程中不会被其他 goroutine 中断
// 常用函数:
// atomic.AddInt32()
// atomic.CompareAndSwapInt32()
// atomic.LoadInt32()
// atomic.StoreInt32()
// import (
// "fmt"
// "sync"
// "sync/atomic"
// )
// var counter int32
// func increment(wg *sync.WaitGroup) {
// defer wg.Done()
// atomic.AddInt32(&counter, 1) // 原子加操作
// }
// func main() {
// var wg sync.WaitGroup
// // 启动多个 goroutine
// for i := 0; i < 5; i++ {
// wg.Add(1)
// go increment(&wg)
// }
// wg.Wait()
// fmt.Println("最终计数:", counter)
// }
// 总结:
// sync 包提供了强大的同步工具,帮助开发者处理并发编程中的数据共享、任务同步和并发安全问题。常用的同步工具有:
// sync.WaitGroup:等待多个 goroutine 完成。
// sync.Mutex:互斥锁,保证同一时刻只有一个 goroutine 访问共享资源。
// sync.RWMutex:读写锁,支持多个 goroutine 同时读取,但写入时会阻塞所有读写操作。
// sync.Once:确保某个操作只执行一次,适用于初始化操作。
// sync/atomic:原子操作,保证在并发环境下的数据操作安全。
}
标签: Golang标准库
Golang 并发编程Demo2 模拟多消费者队列 Golang
package main
import (
"fmt"
"sync"
//"time"
)
//模拟多个工作者与任务队列
//模拟了一个工作池,其中有多个工作者处理多个任务。通过 select,每个工作者可以从任务队列中接收任务并处理。
// 工作者消费方法
func worker(id int,jobs <-chan string,results chan<- string,wg *sync.WaitGroup){
// jobs 为待消费队列,所以这里只需要读取
// results 为消费后结果,这里只需要写入
//消费后执行一次任务完成
defer wg.Done()
for job := range jobs {
//模拟处理工作
//工作处理完成
results <- fmt.Sprintf("工作者 %d 完成任务, %s",id,job)
}
}
func main(){
var wg sync.WaitGroup
// 创建任务队列
jobs := make(chan string,5)
//创建结果队列
results := make(chan string,5)
// 启动worker
for i := 0; i<=3; i++{
wg.Add(1)
go worker(i,jobs,results,&wg)
}
//向队列中添加任务
for i := 1; i<=5; i++ {
jobs <- fmt.Sprintf("任务 %d",i)
}
close(jobs) // 关闭任务队列,表示没有更多任务
go func(){
wg.Wait()
close(results) // 执行完毕,关闭结果通道
}()
// 打印结果
for result := range results{
fmt.Println(result)
}
}
Golang 并发编程Demo1 Golang
package main
import "fmt"
import "sync"
// 并发demo1
// 假如我正在写一个响应用户信息的接口,这个接口需要获取用户基本信息、余额明细这两个比较耗时的操作
// 此时可以通过goroutine开启两个线程,同时处理获取这两个数据的操作,都获取完了以后组合数据响应
func main(){
fmt.Println(getUserData())
}
// 定义一个用户数据结构体
type UserData struct{
BaseInfo string
BalanceInfo string
}
// 获取用户基本信息函数
func getBaseInfo(ch chan<- string){
ch <- "张三"
}
//获取用户余额信息函数
func getBalanceInfo(ch chan<- string){
ch <- "余额"
}
func getUserData() UserData {
// 定义一个WaitGroup 等待所有任务执行完成
var wg sync.WaitGroup
ch1 := make(chan string)
ch2 := make(chan string)
wg.Add(1)
go func(){
defer wg.Done()
getBaseInfo(ch1)
}()
wg.Add(1)
go func(){
defer wg.Done()
getBalanceInfo(ch2)
}()
udata := UserData{
BaseInfo: <-ch1,
BalanceInfo: <-ch2,
}
//wg.Wait 需要放在接收数据后面,否则会导致死锁,因为wg Wait是阻塞的,放在后面,没有接收通道数据
wg.Wait()
return udata
}