Hello,
I recently submitted a proposal to add slice expansion to channel send statements in Go:
The proposal was closed very quickly in the tracker before any community discussion could take place. I would still like to get broader feedback from Go developers, so I’m starting this discussion here.
The idea mirrors existing slice expansion in function calls (for example, append(dst, src...)) and is exactly equivalent to:
Key points:
ch is evaluated before X, both exactly once.
Sends elements in order; blocking, panic-on-closed, and partial-progress behavior are identical to an explicit loop.
Nil/empty slices, zero-length arrays, and empty strings send nothing.
No gofmt change.
Proposed under GOEXPERIMENT=chanspread.
The for _, v := range xs { ch <- v } pattern is common in pipelines and producers. This syntax makes it more concise and consistent with Go’s existing slice expansion idiom.
Questions for you:
Would this improve readability/ergonomics in your code, or is the explicit loop already optimal?
Does applying the existing ... mental model to sends improve language consistency?
Given that iterators now exist, is this shorthand still worthwhile?
Any concerns that it could mislead about blocking or atomicity?
Full proposal text: https://github.com/golang/go/issues/75023
Thanks,
Ruslan.
--
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 visit https://groups.google.com/d/msgid/golang-nuts/5e2a42d1-8a2d-483b-8c05-4cc0a5ab6a8cn%40googlegroups.com.
Thank you Ian, that’s very helpful context.
I understand the concern about implicit loops and the general bias against them in the language design.
My thought here was that this case might be closer to the existing slice expansion at call sites (f(xs...)). In both cases we’re conceptually saying “apply this operation elementwise.” One is a function call, the other is a channel send.
I agree it does expand into a loop, but it’s a loop Go programmers already write constantly in channel pipelines. I hoped that the consistency with the existing ... operator, and the frequency of the for _, v := range xs { ch <- v } pattern, might make it worth considering as one of those “common special cases.”
I appreciate the feedback either way.
What I meant to highlight is the *mental model* programmers already use: when reading `f(xs...)` it is commonly understood as “take all the elements and pass them along.” My thought was that `ch <- xs...` extends that same intuition into channel sends, even though the mechanics differ internally.So the comparison was more about readability and consistency from the user’s perspective
In that sense, `ch <- xs...` is intended as a lightweight, expressive shorthand for a very common loop
воскресенье, 17 августа 2025 г. в 02:25:47 UTC+3, Ian Lance Taylor:On Sat, Aug 16, 2025 at 1:21 AM Ruslan Semagin <pixel....@gmail.com> wrote:
>
> I understand the concern about implicit loops and the general bias against them in the language design.
> My thought here was that this case might be closer to the existing slice expansion at call sites (f(xs...)). In both cases we’re conceptually saying “apply this operation elementwise.” One is a function call, the other is a channel send.
But the function call is not applied elementwise. As I tried to
explain, the slice is passed directly, not element by element. See
https://go.dev/play/p/R4B1wHZMTuL.
Ian
--
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 visit https://groups.google.com/d/msgid/golang-nuts/9e3f90a5-5c3f-444f-a2b8-0b93840253d7n%40googlegroups.com.
Thanks for clarifying, Ian. You are right, variadic expansion doesn’t literally apply element by element — the slice is passed as-is.What I meant to highlight is the *mental model* programmers already use: when reading `f(xs...)` it is commonly understood as “take all the elements and pass them along.” My thought was that `ch <- xs...` extends that same intuition into channel sends, even though the mechanics differ internally.So the comparison was more about readability and consistency from the user’s perspective, not about the underlying implementation. In that sense, `ch <- xs...` is intended as a lightweight, expressive shorthand for a very common loop, similar to how variadics provide an expressive shorthand for building argument lists.
--
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 visit https://groups.google.com/d/msgid/golang-nuts/5ae54324-3904-441d-b3c4-ae41819dc437n%40googlegroups.com.
What part of the semantics of a channel are “ambiguous”?
From: 'Axel Wagner' via golang-nuts <golan...@googlegroups.com>
Sent: Sunday, August 17, 2025 6:45 AM
To: Ruslan Semagin <pixel....@gmail.com>
Cc: golang-nuts <golan...@googlegroups.com>
Subject: Re: [go-nuts] Slice expansion in channel send statements (ch <- X...)
This message was sent by an external party.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHXKxBxUfaWmYJkEdMT6nshYSkd%2B-K0Y45H2PoiRswdCQ%40mail.gmail.com.
In general, it seems to me that much of the opposition here comes from a general reluctance to introduce *any* new syntax into the language.
If I try to summarize the proposal clearly, it is nothing more than syntactic sugar for a very specific case.
This syntactic sugar:
1. Does not complicate the language.
2. Does not break backward compatibility.
3. Leaves the choice to the programmer which form to use in a given situation.
4. Reduces boilerplate in places where the pattern occurs.
5. Does not introduce new semantics or unexpected side effects—its behavior is exactly that of the explicit loop.
6. Can be fully and clearly documented in the language specification, as with other small sugars.
It is not a revolutionary change. It is simply an additional, optional way of writing code in a specific situation.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/eb580a6d-74ab-4b9b-be94-fcdeb25ad2b1n%40googlegroups.com.
On Aug 18, 2025, at 9:41 PM, Ruslan Semagin <pixel....@gmail.com> wrote:Bakul Shah,>The other issue is information loss. If the channel is closed *while* ch<-xs... is active, you don't know *how many* elements were passed.The reader has this information, and can also find out at any time how many elements are already in the channel.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/d4fb4b80-108d-4673-9347-7a352590f843n%40googlegroups.com.
In general, it seems to me that much of the opposition here comes from a general reluctance to introduce *any* new syntax into the language.
If I try to summarize the proposal clearly, it is nothing more than syntactic sugar for a very specific case.
This syntactic sugar:
1. Does not complicate the language.
2. Does not break backward compatibility.
3. Leaves the choice to the programmer which form to use in a given situation.
4. Reduces boilerplate in places where the pattern occurs.
5. Does not introduce new semantics or unexpected side effects—its behavior is exactly that of the explicit loop.
6. Can be fully and clearly documented in the language specification, as with other small sugars.
It is not a revolutionary change. It is simply an additional, optional way of writing code in a specific situation.