Is introducing ... to parameter list a breaking change? How is it considered in the proposal process?

193 views
Skip to first unread message

Changkun Ou

unread,
May 3, 2022, 3:28:27 PM5/3/22
to golang-nuts
Hi gophers,

I wonder how the Go project defines a breaking change, specifically for the case where we have an existing API but want to add ... to its parameter list for customizations.

For instance, we have an API:

package foo
func Bar() {}

And the current code uses this function as:

foo.Bar()

Now, we added a ... to the Bar() and having a new function signature:

func Bar(args ...any) {}

Technically, the language allows the existing users to continue to work:

foo.Bar() // still OK.

As long as we don't change how Bar() behaves by default, it seems that the code that previously used foo.Bar() is still considered valid and not breaking. Is introducing this type of API signature change considered a breaking change in the standard library?
What if we propose API changes like this to the existing standard library, will it be considered differently compared to an actual breaking change?

Thanks!
Changkun

Axel Wagner

unread,
May 3, 2022, 3:37:05 PM5/3/22
to Changkun Ou, golang-nuts
Basically every change to any exported API is a breaking change, strictly speaking. For this case, a user might do
var f func() = pkg.Bar
Which would fail to compile if `pkg.Bar` gains variadic arguments. Similar constructs can be done for any change to the type of any identifier.

That's why the Go 1 compatibility promise (and any notion of compatibility) is essentially reduced to explicitly list the changes it considers allowed. Best I know, it's
  • Adding a method to a type
  • Adding a field to a struct
  • Adding a new exported identifier
However, by extension, you can technically apply whatever compatibility promises you like. It is not entirely uncommon to document that you reserve the right to make certain changes - you could very well document that you would not consider adding variadic parameters a breaking change, so users of your package should not assume it doesn't happen and avoid constructs as above (basically, storing `pkg.Bar` in any variable, unless it uses a short variable declaration and the type of that variable doesn't matter).

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/9e9c58f0-7a79-4c43-9389-72f8d2954080n%40googlegroups.com.

Ian Lance Taylor

unread,
May 3, 2022, 3:38:35 PM5/3/22
to Changkun Ou, golang-nuts
In the standard library we would consider that a breaking change,
because it would break code like

var f = []func() { Bar }

You might be interested in Jonathan Amsterdam's Gophercon talk:
https://www.youtube.com/watch?v=JhdL5AkH-AQ

Ian

Changkun Ou

unread,
May 4, 2022, 2:08:05 AM5/4/22
to golang-nuts
Hi Axel and Ian,

Thanks for the elaborative answer! I was too naive while considering the case and didn't observe the existing practices well. Assignability seems to create a lot more complicated compatibility issues.

Regarding the compatibility promises to users, it always seems the interpretation of developers and users is less effective in this area. I wonder what might be a possible way to involve a successful impact here. Is there any old practice that exists? Especially in the Go project itself :)

Also, the fantastic talk by Jonathan illustrates and saves me potentially a lot of time from a very early attempt to tackle the problem once again.

Changkun

Ian Lance Taylor

unread,
May 5, 2022, 1:47:35 AM5/5/22
to Changkun Ou, golang-nuts
On Tue, May 3, 2022 at 11:08 PM Changkun Ou <ma...@changkun.de> wrote:
>
> Regarding the compatibility promises to users, it always seems the interpretation of developers and users is less effective in this area. I wonder what might be a possible way to involve a successful impact here. Is there any old practice that exists? Especially in the Go project itself :)

I'm not sure exactly what you are asking. In case it helps, the Go
distribution includes a tool in cmd/api that verifies that the
standard library API does not change. If you try to commit an
incompatible change to the standard library, then "go tool dist test
-run=api" will fail. That test runs cmd/api/run.go to test the
standard library.

Ian
Reply all
Reply to author
Forward
0 new messages