Go 自建库的使用教程与测试
附加一个Go库的实现,相较于Python,Go的实现更较为日常,不需要额外增加setup.py类的文件去额外定义,计算和并发的性能更加。
1. 创建 Go 模块项目结构
首先创建完整的项目结构:
gomathlib/
├── go.mod
├── go.sum
├── core/
│ ├── arithmetic.go
│ └── calculator.go
├── advanced/
│ ├── functions.go
│ └── statistics.go
├── constants/
│ └── constants.go
├── examples/
│ ├── basic_usage.go
│ └── advanced_usage.go
├── tests/
│ ├── core_test.go
│ ├── advanced_test.go
│ └── constants_test.go
└── README.md
2. 初始化 Go 模块
# 创建项目目录
mkdir gomathlib
cd gomathlib# 初始化 Go 模块
go mod init github.com/yourusername/gomathlib# 创建目录结构
mkdir -p core advanced constants examples tests
3. 核心代码实现
3.1 go.mod
module github.com/yourusername/gomathlibgo 1.21require (github.com/stretchr/testify v1.8.4
)
3.2 core/arithmetic.go
package coreimport ("errors""math"
)// Arithmetic 提供基础算术运算
type Arithmetic struct {precision int
}// NewArithmetic 创建新的算术运算实例
func NewArithmetic(precision int) *Arithmetic {return &Arithmetic{precision: precision}
}// Add 加法运算,支持多个参数
func (a *Arithmetic) Add(numbers ...float64) float64 {var sum float64for _, num := range numbers {sum += num}return a.round(sum)
}// Subtract 减法运算
func (a *Arithmetic) Subtract(aVal, bVal float64) float64 {return a.round(aVal - bVal)
}// Multiply 乘法运算,支持多个参数
func (a *Arithmetic) Multiply(numbers ...float64) float64 {product := 1.0for _, num := range numbers {product *= num}return a.round(product)
}// Divide 除法运算
func (a *Arithmetic) Divide(dividend, divisor float64) (float64, error) {if divisor == 0 {return 0, errors.New("division by zero is not allowed")}return a.round(dividend / divisor), nil
}// Power 幂运算
func (a *Arithmetic) Power(base, exponent float64) float64 {return a.round(math.Pow(base, exponent))
}// Sqrt 平方根运算
func (a *Arithmetic) Sqrt(number float64) (float64, error) {if number < 0 {return 0, errors.New("cannot calculate square root of negative number")}return a.round(math.Sqrt(number)), nil
}// round 四舍五入到指定精度
func (a *Arithmetic) round(value float64) float64 {if a.precision < 0 {return value}shift := math.Pow(10, float64(a.precision))return math.Round(value*shift) / shift
}
3.3 core/calculator.go
package coreimport ("fmt""strings"
)// Calculator 提供链式计算功能
type Calculator struct {result float64history []stringprecision int
}// NewCalculator 创建新的计算器实例
func NewCalculator(initialValue float64, precision int) *Calculator {return &Calculator{result: initialValue,history: []string{fmt.Sprintf("Initial value: %.2f", initialValue)},precision: precision,}
}// Add 加法操作
func (c *Calculator) Add(value float64) *Calculator {c.result += valuec.history = append(c.history, fmt.Sprintf("+ %.2f", value))return c
}// Subtract 减法操作
func (c *Calculator) Subtract(value float64) *Calculator {c.result -= valuec.history = append(c.history, fmt.Sprintf("- %.2f", value))return c
}// Multiply 乘法操作
func (c *Calculator) Multiply(value float64) *Calculator {c.result *= valuec.history = append(c.history, fmt.Sprintf("* %.2f", value))return c
}// Divide 除法操作
func (c *Calculator) Divide(value float64) (*Calculator, error) {if value == 0 {return nil, fmt.Errorf("division by zero")}c.result /= valuec.history = append(c.history, fmt.Sprintf("/ %.2f", value))return c, nil
}// GetResult 获取当前结果
func (c *Calculator) GetResult() float64 {// 使用内置的round方法shift := math.Pow(10, float64(c.precision))return math.Round(c.result*shift) / shift
}// Clear 清除计算历史
func (c *Calculator) Clear() *Calculator {c.result = 0c.history = []string{"Cleared"}return c
}// GetHistory 获取计算历史
func (c *Calculator) GetHistory() []string {return c.history
}// String 返回计算历史的字符串表示
func (c *Calculator) String() string {return strings.Join(c.history, " → ")
}
3.4 advanced/functions.go
package advancedimport ("errors""math"
)// MathFunctions 提供高级数学函数
type MathFunctions struct{}// NewMathFunctions 创建新的数学函数实例
func NewMathFunctions() *MathFunctions {return &MathFunctions{}
}// Factorial 计算阶乘
func (mf *MathFunctions) Factorial(n int) (int, error) {if n < 0 {return 0, errors.New("factorial is not defined for negative numbers")}if n == 0 {return 1, nil}result := 1for i := 1; i <= n; i++ {result *= i}return result, nil
}// IsPrime 判断是否为质数
func (mf *MathFunctions) IsPrime(n int) bool {if n <= 1 {return false}if n <= 3 {return true}if n%2 == 0 || n%3 == 0 {return false}for i := 5; i*i <= n; i += 6 {if n%i == 0 || n%(i+2) == 0 {return false}}return true
}// Fibonacci 生成斐波那契数列
func (mf *MathFunctions) Fibonacci(n int) ([]int, error) {if n < 0 {return nil, errors.New("n must be non-negative")}if n == 0 {return []int{}, nil}if n == 1 {return []int{0}, nil}if n == 2 {return []int{0, 1}, nil}fib := make([]int, n)fib[0] = 0fib[1] = 1for i := 2; i < n; i++ {fib[i] = fib[i-1] + fib[i-2]}return fib, nil
}// Log 计算对数
func (mf *MathFunctions) Log(number, base float64) (float64, error) {if number <= 0 || base <= 0 || base == 1 {return 0, errors.New("invalid arguments for logarithm")}return math.Log(number) / math.Log(base), nil
}// Sin 计算正弦值(弧度)
func (mf *MathFunctions) Sin(radians float64) float64 {return math.Sin(radians)
}// Cos 计算余弦值(弧度)
func (mf *MathFunctions) Cos(radians float64) float64 {return math.Cos(radians)
}
3.5 advanced/statistics.go
package advancedimport ("errors""math""sort"
)// Statistics 提供统计计算功能
type Statistics struct{}// NewStatistics 创建新的统计实例
func NewStatistics() *Statistics {return &Statistics{}
}// Mean 计算平均值
func (s *Statistics) Mean(numbers []float64) (float64, error) {if len(numbers) == 0 {return 0, errors.New("empty slice provided")}sum := 0.0for _, num := range numbers {sum += num}return sum / float64(len(numbers)), nil
}// Median 计算中位数
func (s *Statistics) Median(numbers []float64) (float64, error) {if len(numbers) == 0 {return 0, errors.New("empty slice provided")}sorted := make([]float64, len(numbers))copy(sorted, numbers)sort.Float64s(sorted)n := len(sorted)if n%2 == 0 {return (sorted[n/2-1] + sorted[n/2]) / 2, nil}return sorted[n/2], nil
}// Mode 计算众数
func (s *Statistics) Mode(numbers []float64) ([]float64, error) {if len(numbers) == 0 {return nil, errors.New("empty slice provided")}frequency := make(map[float64]int)for _, num := range numbers {frequency[num]++}maxFreq := 0for _, freq := range frequency {if freq > maxFreq {maxFreq = freq}}var modes []float64for num, freq := range frequency {if freq == maxFreq {modes = append(modes, num)}}return modes, nil
}// StandardDeviation 计算标准差
func (s *Statistics) StandardDeviation(numbers []float64) (float64, error) {if len(numbers) < 2 {return 0, errors.New("at least two numbers required for standard deviation")}mean, err := s.Mean(numbers)if err != nil {return 0, err}sumSq := 0.0for _, num := range numbers {diff := num - meansumSq += diff * diff}variance := sumSq / float64(len(numbers)-1)return math.Sqrt(variance), nil
}// Variance 计算方差
func (s *Statistics) Variance(numbers []float64) (float64, error) {if len(numbers) < 2 {return 0, errors.New("at least two numbers required for variance")}mean, err := s.Mean(numbers)if err != nil {return 0, err}sumSq := 0.0for _, num := range numbers {diff := num - meansumSq += diff * diff}return sumSq / float64(len(numbers)-1), nil
}
3.6 constants/constants.go
package constants// MathConstants 包含常用数学常量
type MathConstants struct {PI float64E float64GoldenRatio float64EulerMascheroni float64LightSpeed float64
}// NewMathConstants 创建数学常量实例
func NewMathConstants() *MathConstants {return &MathConstants{PI: 3.14159265358979323846,E: 2.71828182845904523536,GoldenRatio: 1.61803398874989484820,EulerMascheroni: 0.57721566490153286060,LightSpeed: 299792458, // m/s}
}// 包级常量
var (PI = 3.14159265358979323846E = 2.71828182845904523536GoldenRatio = 1.61803398874989484820
)
4. 使用教程
4.1 安装依赖
# 下载依赖
go mod tidy# 或者手动安装测试框架
go get github.com/stretchr/testify
4.2 基本使用示例 examples/basic_usage.go
package mainimport ("fmt""log""github.com/yourusername/gomathlib/core""github.com/yourusername/gomathlib/advanced""github.com/yourusername/gomathlib/constants"
)func main() {fmt.Println("=== GoMathLib 基本使用示例 ===")// 基础算术运算arithmetic := core.NewArithmetic(4)fmt.Println("\n1. 基础运算:")fmt.Printf("加法: %.4f\n", arithmetic.Add(1.2345, 2.3456))fmt.Printf("乘法: %.4f\n", arithmetic.Multiply(3, 4, 5))result, err := arithmetic.Divide(22, 7)if err != nil {log.Fatal(err)}fmt.Printf("除法: %.4f\n", result)// 链式计算器fmt.Println("\n2. 链式计算器:")calc := core.NewCalculator(10, 2)calcResult, err := calc.Add(5).Multiply(3).Subtract(2).Divide(4)if err != nil {log.Fatal(err)}fmt.Printf("计算结果: %.2f\n", calcResult.GetResult())fmt.Printf("计算历史: %s\n", calcResult.String())// 高级函数fmt.Println("\n3. 高级函数:")mathFuncs := advanced.NewMathFunctions()factorial, err := mathFuncs.Factorial(5)if err != nil {log.Fatal(err)}fmt.Printf("5的阶乘: %d\n", factorial)fmt.Printf("17是质数: %t\n", mathFuncs.IsPrime(17))fib, err := mathFuncs.Fibonacci(10)if err != nil {log.Fatal(err)}fmt.Printf("斐波那契数列: %v\n", fib)// 数学常量fmt.Println("\n4. 数学常量:")mathConsts := constants.NewMathConstants()fmt.Printf("圆周率: %.10f\n", mathConsts.PI)fmt.Printf("自然常数e: %.10f\n", mathConsts.E)fmt.Printf("黄金比例: %.10f\n", mathConsts.GoldenRatio)fmt.Printf("光速: %.0f m/s\n", mathConsts.LightSpeed)
}
5. 测试用例
5.1 tests/core_test.go
package testsimport ("testing""github.com/yourusername/gomathlib/core""github.com/stretchr/testify/assert"
)func TestArithmetic(t *testing.T) {arithmetic := core.NewArithmetic(4)t.Run("Test Addition", func(t *testing.T) {result := arithmetic.Add(1, 2, 3, 4)assert.Equal(t, 10.0, result)})t.Run("Test Multiplication", func(t *testing.T) {result := arithmetic.Multiply(2, 3, 4)assert.Equal(t, 24.0, result)})t.Run("Test Division", func(t *testing.T) {result, err := arithmetic.Divide(10, 2)assert.NoError(t, err)assert.Equal(t, 5.0, result)})t.Run("Test Division By Zero", func(t *testing.T) {_, err := arithmetic.Divide(10, 0)assert.Error(t, err)})t.Run("Test Precision", func(t *testing.T) {result := arithmetic.Add(1.23456, 2.34567)assert.Equal(t, 3.5802, result) // Rounded to 4 decimal places})
}func TestCalculator(t *testing.T) {t.Run("Test Calculator Chain", func(t *testing.T) {calc := core.NewCalculator(10, 2)result, err := calc.Add(5).Multiply(3).Subtract(2).Divide(4)assert.NoError(t, err)assert.Equal(t, 9.75, result.GetResult())})t.Run("Test Calculator Division By Zero", func(t *testing.T) {calc := core.NewCalculator(10, 2)_, err := calc.Divide(0)assert.Error(t, err)})t.Run("Test Calculator History", func(t *testing.T) {calc := core.NewCalculator(0, 2)calc.Add(5).Multiply(2)history := calc.GetHistory()assert.Len(t, history, 3) // Initial + Add + Multiply})
}
5.2 tests/advanced_test.go
package testsimport ("testing""github.com/yourusername/gomathlib/advanced""github.com/stretchr/testify/assert"
)func TestMathFunctions(t *testing.T) {mathFuncs := advanced.NewMathFunctions()t.Run("Test Factorial", func(t *testing.T) {result, err := mathFuncs.Factorial(5)assert.NoError(t, err)assert.Equal(t, 120, result)})t.Run("Test Factorial Negative", func(t *testing.T) {_, err := mathFuncs.Factorial(-1)assert.Error(t, err)})t.Run("Test IsPrime", func(t *testing.T) {assert.True(t, mathFuncs.IsPrime(2))assert.True(t, mathFuncs.IsPrime(17))assert.False(t, mathFuncs.IsPrime(1))assert.False(t, mathFuncs.IsPrime(15))})t.Run("Test Fibonacci", func(t *testing.T) {result, err := mathFuncs.Fibonacci(10)assert.NoError(t, err)expected := []int{0, 1, 1, 2, 3, 5, 8, 13, 21, 34}assert.Equal(t, expected, result)})
}func TestStatistics(t *testing.T) {stats := advanced.NewStatistics()numbers := []float64{1, 2, 3, 4, 5, 5, 6}t.Run("Test Mean", func(t *testing.T) {result, err := stats.Mean(numbers)assert.NoError(t, err)assert.Equal(t, 3.7142857142857144, result)})t.Run("Test Median", func(t *testing.T) {result, err := stats.Median(numbers)assert.NoError(t, err)assert.Equal(t, 4.0, result)})t.Run("Test Mode", func(t *testing.T) {result, err := stats.Mode(numbers)assert.NoError(t, err)assert.Equal(t, []float64{5}, result)})t.Run("Test Empty Slice", func(t *testing.T) {_, err := stats.Mean([]float64{})assert.Error(t, err)})
}
5.3 tests/constants_test.go
package testsimport ("testing""github.com/yourusername/gomathlib/constants""github.com/stretchr/testify/assert"
)func TestConstants(t *testing.T) {mathConsts := constants.NewMathConstants()t.Run("Test PI", func(t *testing.T) {assert.Equal(t, 3.14159265358979323846, mathConsts.PI)assert.Equal(t, mathConsts.PI, constants.PI)})t.Run("Test E", func(t *testing.T) {assert.Equal(t, 2.71828182845904523536, mathConsts.E)assert.Equal(t, mathConsts.E, constants.E)})t.Run("Test GoldenRatio", func(t *testing.T) {assert.Equal(t, 1.61803398874989484820, mathConsts.GoldenRatio)assert.Equal(t, mathConsts.GoldenRatio, constants.GoldenRatio)})
}
6. 运行测试和示例
6.1 运行测试
# 运行所有测试
go test ./tests/ -v# 运行特定测试
go test ./tests/ -run TestArithmetic -v# 运行带覆盖率的测试
go test ./tests/ -cover -v# 生成HTML覆盖率报告
go test ./tests/ -coverprofile=coverage.out
go tool cover -html=coverage.out
6.2 运行示例
# 运行基本使用示例
go run examples/basic_usage.go# 构建示例
go build -o examples/basic_usage examples/basic_usage.go
./examples/basic_usage
7. 发布和使用
7.1 在其他项目中使用
package mainimport ("fmt""github.com/yourusername/gomathlib/core""github.com/yourusername/gomathlib/advanced"
)func main() {// 使用算术运算math := core.NewArithmetic(2)fmt.Printf("Result: %.2f\n", math.Add(1.23, 4.56))// 使用高级函数adv := advanced.NewMathFunctions()isPrime := adv.IsPrime(29)fmt.Printf("Is 29 prime? %t\n", isPrime)
}
7.2 在其他项目中引用
# 在其他Go项目中引用
go mod init myapp
go mod edit -require github.com/yourusername/gomathlib@v0.1.0
go mod edit -replace github.com/yourusername/gomathlib=../gomathlib
go mod tidy
8. 创建文档
8.1 生成Godoc
# 启动本地Godoc服务器
godoc -http=:6060# 然后在浏览器访问: http://localhost:6060/pkg/github.com/yourusername/gomathlib/
8.2 README.md
# GoMathLib一个功能强大的Go数学运算库,提供基础运算、高级函数和统计计算。## 安装```bash
go get github.com/yourusername/gomathlib
快速开始
package mainimport ("fmt""github.com/yourusername/gomathlib/core"
)func main() {math := core.NewArithmetic(2)result := math.Add(1.23, 4.56)fmt.Printf("Result: %.2f\n", result)
}
功能特性
- 基础四则运算
- 链式计算器
- 高级数学函数(阶乘、质数判断、斐波那契数列)
- 统计计算(平均值、中位数、众数、标准差)
- 数学常量