Go 自建库的使用教程与测试

发布于:2025-09-05 ⋅ 阅读:(16) ⋅ 点赞:(0)

附加一个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/gomathlib

go 1.21

require (
    github.com/stretchr/testify v1.8.4
)

3.2 core/arithmetic.go

package core

import (
	"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 float64
	for _, 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.0
	for _, 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 core

import (
	"fmt"
	"strings"
)

// Calculator 提供链式计算功能
type Calculator struct {
	result   float64
	history  []string
	precision 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 += value
	c.history = append(c.history, fmt.Sprintf("+ %.2f", value))
	return c
}

// Subtract 减法操作
func (c *Calculator) Subtract(value float64) *Calculator {
	c.result -= value
	c.history = append(c.history, fmt.Sprintf("- %.2f", value))
	return c
}

// Multiply 乘法操作
func (c *Calculator) Multiply(value float64) *Calculator {
	c.result *= value
	c.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 /= value
	c.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 = 0
	c.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 advanced

import (
	"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 := 1
	for 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] = 0
	fib[1] = 1
	
	for 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 advanced

import (
	"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.0
	for _, 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 := 0
	for _, freq := range frequency {
		if freq > maxFreq {
			maxFreq = freq
		}
	}
	
	var modes []float64
	for 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.0
	for _, num := range numbers {
		diff := num - mean
		sumSq += 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.0
	for _, num := range numbers {
		diff := num - mean
		sumSq += diff * diff
	}
	
	return sumSq / float64(len(numbers)-1), nil
}

3.6 constants/constants.go

package constants

// MathConstants 包含常用数学常量
type MathConstants struct {
	PI             float64
	E              float64
	GoldenRatio    float64
	EulerMascheroni float64
	LightSpeed     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.14159265358979323846
	E           = 2.71828182845904523536
	GoldenRatio = 1.61803398874989484820
)

4. 使用教程

4.1 安装依赖

# 下载依赖
go mod tidy

# 或者手动安装测试框架
go get github.com/stretchr/testify

4.2 基本使用示例 examples/basic_usage.go

package main

import (
	"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 tests

import (
	"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 tests

import (
	"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 tests

import (
	"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 main

import (
	"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 main

import (
	"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)
}

功能特性

  • 基础四则运算
  • 链式计算器
  • 高级数学函数(阶乘、质数判断、斐波那契数列)
  • 统计计算(平均值、中位数、众数、标准差)
  • 数学常量


网站公告

今日签到

点亮在社区的每一天
去签到