diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..7af6886 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,73 @@ +name: create-release + +on: + push: + branches: + - main # 监听 main 分支的 push 操作(编译和测试/代码检查) + tags: + - 'v*' # 监听以 'v' 开头的标签的 push 操作(发布 Release) + +jobs: + lint: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/setup-go@v5 + with: + go-version: "1.23.x" + - uses: actions/checkout@v4 + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + version: latest + + test: + runs-on: ubuntu-latest + strategy: + matrix: + go: [ "1.22.x", "1.23.x" ] + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go }} + + - name: Run test + run: make test COVERAGE_DIR=/tmp/coverage + + - name: Send goveralls coverage + uses: shogo82148/actions-goveralls@v1 + with: + path-to-profile: /tmp/coverage/combined.txt + flag-name: Go-${{ matrix.go }} + parallel: true + + check-coverage: + name: Check coverage + needs: [ test ] + runs-on: ubuntu-latest + steps: + - uses: shogo82148/actions-goveralls@v1 + with: + parallel-finished: true + + # 发布 Release + release: + name: Release a new version + needs: [ lint, test ] + runs-on: ubuntu-latest + # 仅在推送标签时执行 + if: ${{ success() && startsWith(github.ref, 'refs/tags/v') }} + steps: + # 1. 检出代码 + - name: Checkout code + uses: actions/checkout@v4 + + # 2. 创建 Release 和上传源码包 + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..40326ce --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +COVERAGE_DIR ?= .coverage + +# cp from: https://github.com/yyle88/runpath/blob/93f435829e925c97029ab3e080caed09a780d68b/Makefile#L4 +test: + @-rm -r $(COVERAGE_DIR) + @mkdir $(COVERAGE_DIR) + make test-with-flags TEST_FLAGS='-v -race -covermode atomic -coverprofile $$(COVERAGE_DIR)/combined.txt -bench=. -benchmem -timeout 20m' + +test-with-flags: + @go test $(TEST_FLAGS) ./... diff --git a/README.md b/README.md index 56bc507..a471258 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,138 @@ +[![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/yyle88/tern/release.yml?branch=main&label=BUILD)](https://github.com/yyle88/tern/actions/workflows/release.yml?query=branch%3Amain) +[![GoDoc](https://pkg.go.dev/badge/github.com/yyle88/tern)](https://pkg.go.dev/github.com/yyle88/tern) +[![Coverage Status](https://img.shields.io/coveralls/github/yyle88/tern/master.svg)](https://coveralls.io/github/yyle88/tern?branch=main) +![Supported Go Versions](https://img.shields.io/badge/Go-1.22%2C%201.23-lightgrey.svg) +[![GitHub Release](https://img.shields.io/github/release/yyle88/tern.svg)](https://github.com/yyle88/tern/releases) +[![Go Report Card](https://goreportcard.com/badge/github.com/yyle88/tern)](https://goreportcard.com/report/github.com/yyle88/tern) + # tern -tern is a lightweight Go package for simple, concise ternary expressions, enabling clear conditional logic. + +**`tern`** is a lightweight and versatile Go package designed to simplify conditional logic using concise ternary expressions. With `tern`, you can write clear and expressive code that is easy to read and maintain. + +## README + +[中文说明](README.zh.md) + +## Features + +- **Generic Support**: Fully utilizes Go’s generics, making it type-safe and reusable across a wide range of data types. +- **Flexible Logic**: Supports both direct boolean conditions and conditional functions. +- **Deferred Execution**: Allows lazy evaluation using functions to compute values only when needed, improving performance in certain cases. +- **Zero Value Handling**: Provides utilities to return zero values when no fallback is provided. + +## Installation + +```sh +go get github.com/yyle88/tern +``` + +## Usage + +The `tern` package offers various helper functions for different conditional scenarios: + +### Basic Usage + +```go +package main + +import ( + "fmt" + "github.com/yyle88/tern" +) + +func main() { + // Simple conditional expression + result := tern.BVV(true, "A", "B") + fmt.Println(result) // Output: A + + // Deferred execution for the second value + result = tern.BVF(false, "A", func() string { return "Computed B" }) + fmt.Println(result) // Output: Computed B + + // Using zero values as fallback + result = tern.BV(false, "A") + fmt.Println(result) // Output: (empty string) +} +``` + +### Available Functions + +The `tern` package provides the following functions based on condition types and value evaluation methods: + +| **Function** | **Condition Type** | **First Value** | **Second Value** | +|--------------|--------------------|--------------------------|--------------------------| +| `BVV` | `bool` | Direct value | Direct value | +| `BVF` | `bool` | Direct value | Function returning value | +| `BFV` | `bool` | Function returning value | Direct value | +| `BFF` | `bool` | Function returning value | Function returning value | +| `FVV` | `func() bool` | Direct value | Direct value | +| `FVF` | `func() bool` | Direct value | Function returning value | +| `FFV` | `func() bool` | Function returning value | Direct value | +| `FFF` | `func() bool` | Function returning value | Function returning value | + +Additionally, utility functions like `BV`, `BF`, `FV`, and `FF` simplify zero-value fallbacks. + +### Lazy Evaluation Example + +Using deferred execution ensures unnecessary computations are avoided: + +```go +func computeHeavyValue() string { + fmt.Println("Heavy computation...") + return "Heavy Result" +} + +result := tern.BVF(false, "Default", computeHeavyValue) +// Output: Default (computeHeavyValue() is not executed) +``` + +### Custom Zero Values + +The package uses Go’s `Zero[T]()`, which automatically provides the zero value for any type: + +```go +package main + +import ( + "fmt" + "github.com/yyle88/tern" +) + +func main() { + fmt.Println(tern.Zero[int]()) // Output: 0 + fmt.Println(tern.Zero[string]()) // Output: (empty string) +} +``` + +## Why Use `tern`? + +1. **Readability**: Simplifies conditional logic, making the code easier to follow. +2. **Flexibility**: Works seamlessly with both direct values and deferred computation. +3. **Performance**: Avoids unnecessary computation by using lazy evaluation. +4. **Generics**: Leverages Go’s generics for maximum flexibility and type safety. + +## Contributing + +Contributions are welcome! If you’d like to improve the package or fix a bug, feel free to open an issue or submit a pull request on [GitHub](https://github.com/yyle88/tern). + +## License + +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details. + +--- + +## Contributing + +Feel free to contribute or improve the package! Stars and pull requests are always welcome! + +Thank you for using `tern`! + +--- + +## See stars + +[![see stars](https://starchart.cc/yyle88/tern.svg?variant=adaptive)](https://starchart.cc/yyle88/tern) + +Give me stars! Thank you!!! + +--- diff --git a/README.zh.md b/README.zh.md new file mode 100644 index 0000000..dcc3df7 --- /dev/null +++ b/README.zh.md @@ -0,0 +1,122 @@ +# tern + +**`tern`** 是一个轻量且灵活的 Go 包,用于通过简洁的三元表达式简化条件逻辑。使用 `tern`,您可以编写清晰且易于维护的代码。 + +## README + +[ENGLISH-DOC](README.md) + +## 功能特性 + +- **泛型支持**:充分利用 Go 的泛型功能,实现类型安全,可复用性强。 +- **灵活的逻辑**:支持直接的布尔条件和基于函数的条件逻辑。 +- **延迟执行**:支持使用函数进行懒加载,仅在需要时计算值,从而提升性能。 +- **零值处理**:提供工具函数,当无后备值时返回类型的零值。 + +## 安装 + +```sh +go get github.com/yyle88/tern +``` + +## 使用说明 + +`tern` 包提供了针对不同条件场景的多种辅助函数: + +### 基本用法 + +```go +package main + +import ( + "fmt" + "github.com/yyle88/tern" +) + +func main() { + // 简单的条件表达式 + result := tern.BVV(true, "A", "B") + fmt.Println(result) // 输出: A + + // 为第二个值使用延迟执行 + result = tern.BVF(false, "A", func() string { return "计算出的 B" }) + fmt.Println(result) // 输出: 计算出的 B + + // 使用零值作为后备值 + result = tern.BV(false, "A") + fmt.Println(result) // 输出: (空字符串) +} +``` + +### 提供的函数 + +`tern` 包根据条件类型和值的计算方式提供以下函数: + +| **函数名称** | **条件类型** | **第一个值** | **第二个值** | +|----------|---------------|----------|----------| +| `BVV` | `bool` | 直接值 | 直接值 | +| `BVF` | `bool` | 直接值 | 返回值的函数 | +| `BFV` | `bool` | 返回值的函数 | 直接值 | +| `BFF` | `bool` | 返回值的函数 | 返回值的函数 | +| `FVV` | `func() bool` | 直接值 | 直接值 | +| `FVF` | `func() bool` | 直接值 | 返回值的函数 | +| `FFV` | `func() bool` | 返回值的函数 | 直接值 | +| `FFF` | `func() bool` | 返回值的函数 | 返回值的函数 | + +此外,诸如 `BV`、`BF`、`FV` 和 `FF` 等工具函数用于简化返回零值的场景。 + +### 延迟计算示例 + +使用延迟执行可以避免不必要的计算: + +```go +func computeHeavyValue() string { + fmt.Println("执行重计算...") + return "计算结果" +} + +result := tern.BVF(false, "默认值", computeHeavyValue) +// 输出: 默认值 (computeHeavyValue() 不会被执行) +``` + +### 自定义零值 + +该包使用 Go 的 `Zero[T]()`,可自动为任何类型提供零值: + +```go +package main + +import ( + "fmt" + "github.com/yyle88/tern" +) + +func main() { + fmt.Println(tern.Zero[int]()) // 输出: 0 + fmt.Println(tern.Zero[string]()) // 输出: (空字符串) +} +``` + +## `tern` 有什么优势? + +1. **可读性**:简化条件逻辑,使代码更易理解。 +2. **灵活性**:兼容直接值和延迟计算。 +3. **性能**:通过懒加载避免不必要的计算。 +4. **泛型支持**:利用 Go 泛型实现最大灵活性和类型安全。 + +## 贡献指南 + +欢迎贡献代码!如果您希望改进此包或修复 Bug,请随时在 [GitHub](https://github.com/yyle88/tern) 上提交 issue 或 pull request。 + +## 许可证 + +项目采用 MIT 许可证。详情请参阅 [LICENSE](LICENSE) 文件。 + +## 其它 + +我的函数名很简单。 + +## 谢谢 +有兴趣的可以试用。 + +希望大家给个星星。