向函数添加可变参数会破坏现有代码吗? [英] Could adding variadic parameters to a function break existing code?

查看:84
本文介绍了向函数添加可变参数会破坏现有代码吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在现有的Go函数中添加可变参数是一项重大更改吗?

Is adding a variadic parameter to an existing Go function a breaking change?

例如:

// Old function
func Foo(a int)

// Updated to:
func Foo(a int, params ...string)

API的调用者可以忽略新参数,因此我认为API是向后兼容的.

Callers of the API can omit the new parameter, so I would think the API is backwards-compatible.

任何人都可以提供一个示例,其中旧API的用户无法在不更改其代码的情况下使用新API吗?

Can anyone provide an example where a user of the old API could not use the new API without changing their code?

推荐答案

I.更改功能

调用它们将继续工作,而无需进行修改,但是由于功能签名不匹配,因此很容易破坏某些代码.

I. Changing functions

Calling them will continue to work without modification, but since the function signatures do not match, that may easily break some code.

例如(在游乐场上尝试):

func Foo(a int)                    {}
func Foo2(a int, params ...string) {}

func main() {
    var f func(int)

    f = Foo
    f = Foo2 // Compile-time error!

    _ = f
}

f = Foo2行会产生编译时错误:

The line f = Foo2 produces a compile-time error:

不能在分配中使用Foo2(func(int,... string)类型作为func(int)类型

cannot use Foo2 (type func(int, ...string)) as type func(int) in assignment

这是向后不兼容的更改,请不要这样做.

So this is a backward incompatible change, don't do it.

上面的示例给出了一个编译时错误,这是幸运的/更好的情况,但是也可能有一些代码只会在运行时失败(如果/发生,则是不确定的),例如此示例:

The above example gave a compile-time error, which is the lucky / better case, but there may also be code that would only fail at runtime (non-deterministic if / when that happens), like in this example:

func Foo(a int)                    {}
func Foo2(a int, params ...string) {}

func main() {
    process(Foo)
    process(Foo2) // This will panic at runtime (type assertion will not hold)!
}

func process(f interface{}) {
    f.(func(int))(1)
}

调用process(foo)成功,调用process(foo2)将在运行时出现紧急情况.在游乐场上进行尝试.

Calling process(foo) succeeds, calling process(foo2) will panic at runtime. Try it on the Go Playground.

您的问题直接针对函数,但方法也存在相同的问题"(当用作方法表达式方法值,例如,请参见golang-函数的传递方法).

Your question was directed at functions, but the same "problem" exists with methods too (when used as method expressions or method values, for example see golang - pass method to function).

此外,这可能会破坏隐式接口的实现(可能使类型不实现接口),例如在此示例中(在去游乐场):

Additionally, this may break implicit interface implementations (it may make types not implement interfaces), like in this example (try it on the Go Playground):

type Fooer interface {
    Foo(int)
}

type fooImpl int

func (fooImpl) Foo(a int) {}

type fooImpl2 int

func (fooImpl2) Foo(a int, params ...string) {}

func main() {
    var f Fooer

    f = fooImpl(0)
    f = fooImpl2(0) // Compile time error!

    _ = f
}

因为签名不匹配,所以即使fooImpl做到了,fooImpl2也不会实现Fooer:

Because signatures don't match, fooImpl2 does not implement Fooer, even though fooImpl does:

cannot use fooImpl2(0) (type fooImpl2) as type Fooer in assignment:
  fooImpl2 does not implement Fooer (wrong type for Foo method)
      have Foo(int, ...string)
      want Foo(int)

这篇关于向函数添加可变参数会破坏现有代码吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆