Go 变长参数函数的实现示例

 更新时间:2026年04月14日 09:04:41   作者:Go_error  
本文主要介绍了Go语言中的变长参数的类型、声明、调用以及其在实际开发中的应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1. 变长参数和变长参数函数类型

  • 一个函数的最后一个参数可以是一个变长参数;
  • 一个函数可以最多有一个变长参数;
  • 一个变长参数的类型总为一个切片类型。

变长参数在声明的时候必须在它的(切片)类型的元素类型前面前置三个点 ...,以示这是一个变长参数。 两个变长函数类型的例子:

func (values ...int64) (sum int64) 
func (sep string, tokens ...string) string

2. 变长参数函数的声明

变长函数声明和普通函数声明类似,只不过最后一个参数必须为变长参数。一个变长参数在函数体内将被视为一个切片。

func Sum(values ...int64) (sum int64) {
 // values的类型为[]int64
 sum = 0
 for _, v := range values {
  sum += v
 }
 return
}

func Concat(sep string, tokens ...string) (r string) {
 // tokens的类型为[]string
 for i, t := range tokens {
  if i != 0 {
   r += sep
  }
  r += t
 }
 return r
}

从上面的两个变长参数函数声明可以看出,如果一个变长参数的类型部分为 ...T,则此变长参数的类型实际为 []T。

事实上,fmt 标准库包中的 Print、Println 和 Printf 函数均为变长参数函数。它们的声明大致如下:

func Print(a ...interface{}) (n int, err error)
func Printf(format string, a ...interface{}) (n int, err error)
func Println(a ...interface{}) (n int, err error)

3. 变长参数函数调用

在变长参数函数调用中,可以使用两种风格的方式将实参传递给类型为 []T 的变长形参:

1.传递一个切片做为实参。此切片必须可以被赋值给类型为 []T 的值(或者说此切片可以被隐式转换为类型 []T)。此实参切片后必须跟随三个点 ...。

2.传递零个或者多个可以被隐式转换为 T 的实参(或者说这些实参可以赋值给类型为 T 的值)。 这些实参将被添加入一个匿名的在运行时刻创建的类型为 []T 的切片中,然后此切片将被传递给此函数调用。

注意,这两种风格的方式不可在同一个变长参数函数调用中混用。

下面这个例子展示了一些变长参数函数调用:

package main

import "fmt"

func Sum(values ...int64) (sum int64) {
 sum = 0
 for _, v := range values {
  sum += v
 }
 return
}

func main() {
 a0 := Sum()
 a1 := Sum(2)
 a3 := Sum(2, 3, 5)
 // 上面三行和下面三行是等价的。
 b0 := Sum([]int64{}...)
 b1 := Sum([]int64{2}...)
 b3 := Sum([]int64{2, 3, 5}...)
 fmt.Println(a0, a1, a3) // 0 2 10
 fmt.Println(b0, b1, b3) // 0 2 10
}

4. 模拟实现函数的可选参数与默认参数

来看下 Gin 中的 Run 方法使用:

func (engine *Engine) Run(addr ...string) (err error) {
 defer func() { debugPrintError(err) }()

 address := resolveAddress(addr)
 debugPrint("Listening and serving HTTP on %s\n", address)
 err = http.ListenAndServe(address, engine)
 return
}


func resolveAddress(addr []string) string {
 switch len(addr) {
 case 0:
  if port := os.Getenv("PORT"); port != "" {
   debugPrint("Environment variable PORT="%s"", port)
   return ":" + port
  }
  debugPrint("Environment variable PORT is undefined. Using port :8080 by default")
  return ":8080"
 case 1:
  return addr[0]
 default:
  panic("too many parameters")
 }
}

5. 实现功能选项模式(functional option)

功能选项模式使得我们在设计和实现带有配置选项的函数或方法时,更灵活优雅:

package main
import "fmt"
type CoffeeOptions struct {
 sugar        int
 milk         int
 coffeePowder int
}
// 这个函数会接受上面结构体 CoffeeOptions 实例的指针 这个函数最终的目的都是为了修改实例
type CoffeeOption func(*CoffeeOptions)
// 下面这三个函数都会返回 CoffeeOption 函数 方便修改 CoffeeOptions 结构体
func CoffeeSugar(sugar int) CoffeeOption {
 return func(opts *CoffeeOptions) {
  opts.sugar = sugar
 }
}
func CoffeeMilk(milk int) CoffeeOption {
 return func(opts *CoffeeOptions) {
  opts.milk = milk
 }
}
func CoffeePowder(coffeePowder int) CoffeeOption {
 return func(opts *CoffeeOptions) {
  opts.coffeePowder = coffeePowder
 }
}
func newDefaultCoffeeOptions() *CoffeeOptions {
 return &CoffeeOptions{
  sugar:        5,
  milk:         0,
  coffeePowder: 60,
 }
}
func NewCoffee(opts ...CoffeeOption) *CoffeeOptions {
 // 新建实例opt
 defaultOptions := newDefaultCoffeeOptions()
 // 根据所传的参数修改opt实例
 for _, o := range opts {
  o(defaultOptions)
 }
 return defaultOptions
}
func main() {
 // 创建函数来修改实例
 opts := NewCoffee(
  CoffeeSugar(10),
  CoffeeMilk(10),
  CoffeePowder(80),
 )
 fmt.Printf("%#v", *opts)
 // main.CoffeeOptions{sugar:10, milk:10, coffeePowder:80}
}

go-micro 中你可以看到很多 functional option 的应用,基本每个 micro 组件都使用了这种方式进行构造。

到此这篇关于Go 变长参数函数的实现示例的文章就介绍到这了,更多相关Go 变长参数函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang判断两个链表是否相交的方法详解

    Golang判断两个链表是否相交的方法详解

    这篇文章主要为大家详细介绍了如何通过Golang判断两个链表是否相交,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-03-03
  • Go官方限流器的用法详解

    Go官方限流器的用法详解

    限流器是提升服务稳定性的非常重要的组件,本文主要介绍了Go官方限流器的用法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • Go语言调用DeepSeek API实现流式输出和对话

    Go语言调用DeepSeek API实现流式输出和对话

    DeepSeek是一个强大的AI模型服务平台,本文将详细介绍如何使用Go语言调用DeepSeek API实现流式输出和对话功能,感兴趣的小伙伴可以了解一下
    2025-02-02
  • Golang 语言map底层实现原理解析

    Golang 语言map底层实现原理解析

    这篇文章主要介绍了Golang 语言map底层实现原理解析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • 搭建Go语言的ORM框架Gorm的具体步骤(从Java到go)

    搭建Go语言的ORM框架Gorm的具体步骤(从Java到go)

    很多朋友不知道如何使用Goland软件,搭建一个ORM框架GORM,今天小编给大家分享一篇教程关于搭建Go语言的ORM框架Gorm的具体步骤(从Java到go),感兴趣的朋友跟随小编一起学习下吧
    2022-09-09
  • Go语言实现AOI区域视野管理流程详解

    Go语言实现AOI区域视野管理流程详解

    在游戏中,场景里存在大量的物体.如果我们把所有物体的变化都广播给玩家.那客户端很难承受这么大的压力.因此我们肯定会做优化.把不必要的信息过滤掉.如只关心玩家视野所看到的.减轻客户端的压力,给玩家更流畅的体验
    2023-03-03
  • Go语言中html/template模块详细功能介绍与示例代码

    Go语言中html/template模块详细功能介绍与示例代码

    这篇文章主要介绍了Go语言中html/template模块详细功能介绍与示例代码,这里说的是go 语言中自带的包html/template里的一些基本操作,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-03-03
  • Go语言命令行操作命令详细介绍

    Go语言命令行操作命令详细介绍

    这篇文章主要介绍了Go语言命令行操作命令详细介绍,本文重点介绍了go build、go clean、go fmt、go get等命令,需要的朋友可以参考下
    2014-10-10
  • gorm FirstOrCreate和受影响的行数实例

    gorm FirstOrCreate和受影响的行数实例

    这篇文章主要介绍了gorm FirstOrCreate和受影响的行数实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • go实现thrift的网络传输性能及需要注意问题示例解析

    go实现thrift的网络传输性能及需要注意问题示例解析

    这篇文章主要为大家介绍了go实现thrift的网络传输性能及需要注意问题示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09

最新评论