Amateur's questions about "Go lang spec"

879 views
Skip to first unread message

Kamil Ziemian

unread,
Oct 28, 2021, 1:33:27 PM10/28/21
to golang-nuts
Hello,

From what I understand proper Gopher read at least one time "The Go Programming Language Specification" (https://golang.org/ref/spec) and now I need to read it too.

I learn something of Extended Backus-Naur Form to understand it, so if I say something stupid beyond belief, I hope you will forgive me. In the first part "Notation" (https://golang.org/ref/spec#Notation) I believe that I understand meaning of all concepts except of "production_name". On one hand "production_name" means that it is name of the production, not rocket science here. On the other, after reading about EBNF I feel that I should have more information about it. Can you explain it to me?

Again I'm new to EBNF, so maybe this is stupid question.

Best
Kamil

Sean Liao

unread,
Oct 28, 2021, 3:31:07 PM10/28/21
to golang-nuts
There isn't much to it, a "production_name" is just an identifier for the set of values defined on the other side of the =, some of which may also be identifiers that should be dereferenced/expanded

If it helps, there's a wikipedia entry on it: https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form

Kamil Ziemian

unread,
Oct 29, 2021, 6:52:54 AM10/29/21
to golang-nuts
From what I understand about EBNF production_name should be defined using EBNF notation in manner like below.

production_name = something1 | something2

But I don't see such definition in Spec.

Best
Kamil

Jan Mercl

unread,
Oct 29, 2021, 7:29:16 AM10/29/21
to Kamil Ziemian, golang-nuts
On Fri, Oct 29, 2021 at 12:53 PM Kamil Ziemian <kziem...@gmail.com> wrote:
>
> From what I understand about EBNF production_name should be defined using EBNF notation in manner like below.
>
> production_name = something1 | something2
>
> But I don't see such definition in Spec.

Because production_name is a terminal symbol of the EBNF grammar per se.

""""
Lower-case production names are used to identify lexical tokens.
Non-terminals are in CamelCase.
""""

src: https://golang.org/ref/spec#Notation

The above link defines a meta-grammar, ie. a grammar of the EBNF
grammar in which the actual Go EBNF grammar is later on defined. In
the Go case the terminals are really defined, like here
https://golang.org/ref/spec#Letters_and_digits.

The EBNF grammar per se is outlined only loosely and is strictly not
complete in this case, so you're right. The reader is expected to
assume "usual" grammar of an identifier, like "a letter followed by 1
or more letters or digits", for example. The "real" definition of EBNF
can be found for example here:
https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form. It
seems too long to include in the Go specs, moreover I think it even
differs in some details.

-j

Kamil Ziemian

unread,
Oct 29, 2021, 9:59:28 AM10/29/21
to golang-nuts
Thank you Jan Marcel, now I understand this part of Spec. I now will go back to read rest of it.

Best
Kamil

Kamil Ziemian

unread,
Oct 29, 2021, 10:22:58 AM10/29/21
to golang-nuts
Thank you Patryk Węgrzynek for these notes. I often feel uneasy when things like "ways of comunications” are unclean to me just at the beginning of reading of text. I like have everything clear at start and you help me clear some mess in my head.

Best
Kamil

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/xwavrjBZbeE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/413421f3-914c-4a71-8cd5-4464b8262802n%40googlegroups.com.

Patryk Węgrzynek

unread,
Oct 29, 2021, 1:05:02 PM10/29/21
to Kamil Ziemian, golang-nuts
In order to standardize something, you need to establish things
thanks to which you are able to express what you want to say.

For example a Notation.

The Go Reference manual uses Extended Backus-Naur Form (EBNF) for that and this part is just expressing that.
Think of this point not as "Go documentation," but as establishing a "way to communicate".

The excerpt you are asking about defines Production's syntax:
Production = production_name "=" [ Expression ] "." .
and a little further down you have an explanation of what Productions is:
Productions are expressions constructed from terms and the following operators, in increasing precedence.

So in other words, we are defining here the syntax that will be used later in the documentation, not the specific fields
and that is why you can not find "production_name" throughout the rest of the docs.
However, for example, hex_digit is a in-docs Production built similarly to what you are looking for:
hex_digit = "0" … "9" | "A" … "F" | "a" … "f" .

Best Regards,

--
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/02647258-d529-4dac-ac63-8c72874b4a89n%40googlegroups.com.


--

Patryk Węgrzynek

Backend Developer
Site Reliability Engineer

Kamil Ziemian

unread,
Nov 7, 2021, 1:22:44 PM11/7/21
to golang-nuts
Hello,

I go back to reading Go spec and I read about omitting semicolon in Go code. I know from some Rob Pike talks on YT or similar source, that compiler inserts semicolon in "places where C programmer would expected it to write". And since I try to follow Go style of writing code (Emacs also helps), outside "if", "for", "switch" and maybe "select" (I really works with channels), I probably never need to write semicolon myself.

To avoid making myself looking stupid by not knowing why simple Go program doesn't compile, when I read part of spec  "Semicolons" (https://golang.org/ref/spec#Semicolons), I try to work out where these semicolons are placed. First rule is easy, but second "To allow complex statements to occupy a single line, a semicolon may be omitted before a closing ")" or "}".", is quite hard to me.

Can anyone give me explicit example when semicolon is omitted in accordance to the second rule and explanation where it should be? I probably see such situations dozens of times, I just not know that they would needed semicolon in some places.

Best
Kamil

Jan Mercl

unread,
Nov 7, 2021, 1:34:41 PM11/7/21
to Kamil Ziemian, golang-nuts
On Sun, Nov 7, 2021 at 7:23 PM Kamil Ziemian <kziem...@gmail.com> wrote:

> Can anyone give me explicit example when semicolon is omitted in accordance to the second rule and explanation where it should be? I probably see such situations dozens of times, I just not know that they would needed semicolon in some places.

I think this is a simple example: https://play.golang.org/p/ZfKxTos6GjY

Click "Run" to see the code is valid, then "Format" to watch one
semicolon disappear and then "Run" again to see it's still valid code.

Kamil Ziemian

unread,
Nov 8, 2021, 4:59:23 AM11/8/21
to golang-nuts
Thank you Jan Mercl, now I start to understand this rule.

Best
Kamil

Kamil Ziemian

unread,
May 4, 2023, 6:20:35 AM5/4/23
to golang-nuts
Hello,

In the section "Type identity" of Go Spec we read a list of type declarations
`type (
A0 = []string
A1 = A0
A2 = struct{ a, b int }
A3 = int
A4 = func(A3, float64) *A0
A5 = func(x int, _ float64) *[]string

// Part unimportant for my point.
)`
and then we have list of types that are identical. Among them we can find text
"[]int and []int"
It is obviously true, but feel out of place. I make a humble guess that authors intended something along the lines
"[]A3 and []int"
Can someone look at this part of Go Spec? I feel that someone make a mistake, but at the same time humble me saying that there is any mistake in the Go Spec is something that I shouldn't do.

Best regards,
Kamil

Kamil Ziemian

unread,
May 4, 2023, 6:34:51 AM5/4/23
to golang-nuts
There is a second such example just below "[]int and []int", but to understand it we need some more type declarations, I listed them below.

`type (
A0 = []string
A1 = A0
A2 = struct{ a, b int }
A3 = int
A4 = func(A3, float64) *A0
A5 = func(x int, _ float64) *[]string

B0 A0
B1 []string
B2 struct{ a, b int }
B3 struct{ a, c int }
B4 func(int, float64) *B0
B5 func(x int, y float64) *A1

// Unimportant part.
)`
The line in question is
"struct{ a, b *B5 } and struct{ a, b *B5 }"
which is true, but again feel out of place. I only start grasping rules of types identity, but I make guess that it should be something like
"struct{ a, b *A5 } and struct{ a, b *B5 }"

Of course it my just be that I'm just stupid. Feel free to inform me that indeed I have no idea what is going on in the Go Spec.

Best regards,
Kamil

Axel Wagner

unread,
May 4, 2023, 8:12:25 AM5/4/23
to Kamil Ziemian, golang-nuts
Personally, I'd rather add more examples of "self-evidently equal types". In my opinion, all the type aliases in that block confuse matters quite a bit.

"[]int and []int are identical" is not actually self-evident at all. It is self-evident that any sensible definition of type identity *should* make them identical. But it's not self-evident that the given definition *does*. Spelling that out in the example, means you are nudged to look at the definition and see how their identity follows (by finding "Two slice types are identical if they have identical element types").

In fact, whenever you define an equivalence relation, proving that it is reflexive is the very first step. And it's not always trivial. For example, `==` on `float64` is *not* reflexive. It seems obvious that NaN == NaN *should* hold from how it's spelled - but it doesn't.

So, I disagree that the examples should limit themselves to cases where it's non-obvious that the two types should be identical.

--
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.

Kamil Ziemian

unread,
May 4, 2023, 10:38:50 AM5/4/23
to golang-nuts
You convince me to your point Axel Wagner. At the same time if we look at examples in Go Spec, I think their can be improved.
"A0, A1, and []string
A2 and struct{ a, b int }
A3 and int A4, func(int, float64) *[]string, and A5

B0 and C0
D0[int, string] and E0
[]int and []int
struct{ a, b *B5 } and struct{ a, b *B5 }
func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5"
I mean, first we need to check that A0, A1 and []string are the same type and after few examples like D0[int, string] is the same as E0, we have stated []int and []int are the same type. If you convince yourself that A0 is the same as A1 and both are the same as []string, checking that []int has the same type as []int is quite trivial. I would prefer that examples would start from basic cases like []int is []int and []A3 is []int (if this one is true) and progress to more convoluted like D0[int, string] is E0.

Best regards,
Kamil

Kamil Ziemian

unread,
Jun 3, 2023, 3:13:28 PM6/3/23
to golang-nuts
Is this example found in the "Composite literals" section of Go Spec a joke?
// list of prime numbers
primes := []int{2, 3, 5, 7, 9, 2147483647}

I checked on the internet and 2147483647 is a prime number (https://en.wikipedia.org/wiki/2,147,483,647), so this element is fine.

Best regards
Kamil

peterGo

unread,
Jun 3, 2023, 3:40:04 PM6/3/23
to golang-nuts

Kamil Ziemian,

// list of prime numbers
primes := []int{2, 3, 5, 7, 9, 2147483647}

The variable prime is a list of some prime numbers starting with the lowest and ending with the highest prime numbers that can safely be represented an int. An int may either 32 or 64 bits.

Please explain the joke.

Note: “Explaining a joke is like dissecting a frog. You understand it better but the frog dies in the process.”
E.B. White

peter

burak serdar

unread,
Jun 3, 2023, 3:52:37 PM6/3/23
to peterGo, golang-nuts
On Sat, Jun 3, 2023 at 1:40 PM peterGo <go.pe...@gmail.com> wrote:

Kamil Ziemian,

// list of prime numbers
primes := []int{2, 3, 5, 7, 9, 2147483647}

The variable prime is a list of some prime numbers starting with the lowest and ending with the highest prime numbers that can safely be represented an int. An int may either 32 or 64 bits.

Please explain the joke.

Could it be that 9 is not prime?
 

Kamil Ziemian

unread,
Jun 3, 2023, 4:07:15 PM6/3/23
to golang-nuts
As burak serdar said, 9 = 3 * 3 is not a prime number, all other elements in the slice are prime numbers. It looks like authors of Go Spec want to make a joke or check how well people read examples in it.

Best regards,
Kamil

peterGo

unread,
Jun 3, 2023, 5:04:56 PM6/3/23
to golang-nuts
It's a simple typo. Send in a fix.

peter

Sean Liao

unread,
Jun 3, 2023, 5:48:52 PM6/3/23
to golang-nuts

Kamil Ziemian

unread,
Jun 10, 2023, 1:12:55 PM6/10/23
to golang-nuts
This is not a complaint, but a reflection. I have read, as careful as I can, the half of the Go Spec and if I didn't learn how parametric polymorphism (generics; did I spell it right) should work from proposals and talks on YouTube, I would probably understand 30% less from it. I know that how parametric polymorphis works in Go and how is described in Spec is not in 100% identical with proposals, but it is good enough. Due to them I have overall picture of what type parameters and related concepts are, so I can guess what is the intention behind part of the Spec that mention type them.

I think I just wouldn't be able learn parametric polymorphism from reading Spec. Things related to it are scattered across the text (this is not a complaint, I just notice a fact) and gathering them together is not a easy task.

I should note, that I want to use parametric polymorphism as really as possible. For me this is a feature of the last resort, but one that you should know that exists.

Needless to say, I will need to read Spec one more time in the future, at least.

Best regards,
Kamil

Axel Wagner

unread,
Jun 10, 2023, 3:44:22 PM6/10/23
to Kamil Ziemian, golang-nuts
If it helps, I don't think I really understand the generics parts of the spec myself.

Kamil Ziemian

unread,
Jun 10, 2023, 4:14:08 PM6/10/23
to golang-nuts
Thank you for encouraging words about generic in spec. Knowing that much more skilled people than I also have problem with understanding this part of spec, give my self assessment a boost.

Kamil Ziemian

unread,
Jun 11, 2023, 11:17:01 AM6/11/23
to golang-nuts
I have some hair splitting question. In the "Conversions to and from a string type" we read:
"Converting a signed or unsigned integer value to a string type yields a string containing the UTF-8 representation of the integer."

Would it be more corrected to say, that conversion from integer to string gives you UTF-8 representation of code point described by value of the integer? Or maybe it is indeed representation of integer described by UTF-8 specification?

Best regards,
Kamil

Axel Wagner

unread,
Jun 11, 2023, 1:03:44 PM6/11/23
to Kamil Ziemian, golang-nuts
I'm not entirely sure. I don't think your phrasing is correct, as it doesn't represent what happens if the integer value exceeds the range of valid codepoints (i.e. if it needs more than 32 bits to represent). That being said, the sentence as is also isn't really precise about it. From what I can tell, the result is not valid UTF-8 in any case.

I think it might make sense to file an issue about this, though in general that conversion is deprecated anyway and gets flagged by `go vet` (and `go test`) because it is not what's usually expected. So I'm not sure how important it is to get this exactly right and understandable.


--
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.

Axel Wagner

unread,
Jun 11, 2023, 1:10:56 PM6/11/23
to Kamil Ziemian, golang-nuts
Ah, the spec does actually say:
Converting a signed or unsigned integer value to a string type yields a string containing the UTF-8 representation of the integer. Values outside the range of valid Unicode code points are converted to "\uFFFD".

Personally, I think this is fine as is. I think people understand what happens from these two sentences. 

Rob Pike

unread,
Jun 11, 2023, 8:02:27 PM6/11/23
to Axel Wagner, Kamil Ziemian, golang-nuts
Although the sentence is OK as it stands, the section should be tweaked a bit. One of the examples there (myString(0x65e5)) is valid Go but vet rejects it, as part of the move towards disallowing this conversion, which was there mostly for bootstrapping the libraries.

-rob


Kamil Ziemian

unread,
Jul 28, 2023, 10:03:51 AM7/28/23
to golang-nuts
Hello,

After a long break, I go back to reading Go Spec.

In the section "Expression statements" we read that "The following built-in functions are not permitted in statement context:

append cap complex imag len make new real
unsafe.Add unsafe.Alignof unsafe.Offsetof unsafe.Sizeof unsafe.Slice

h(x+y)
f.Close()
<-ch
(<-ch)
len("foo")  // illegal if len is the built-in function"

Are things following "h(x+y)" also forbidden in the statement context? This part of spec isn't specially clear in my opinion.

Best regards,
Kamil

Axel Wagner

unread,
Jul 28, 2023, 10:43:10 AM7/28/23
to Kamil Ziemian, golang-nuts
On Fri, Jul 28, 2023 at 4:04 PM Kamil Ziemian <kziem...@gmail.com> wrote:
Hello,

After a long break, I go back to reading Go Spec.

In the section "Expression statements" we read that "The following built-in functions are not permitted in statement context:

append cap complex imag len make new real
unsafe.Add unsafe.Alignof unsafe.Offsetof unsafe.Sizeof unsafe.Slice

h(x+y)
f.Close()
<-ch
(<-ch)
len("foo")  // illegal if len is the built-in function"

Are things following "h(x+y)" also forbidden in the statement context? This part of spec isn't specially clear in my opinion.

No, they are not. Otherwise, they'd have a comment following them saying "illegal for $reason".
 

Axel Wagner

unread,
Jul 28, 2023, 10:51:20 AM7/28/23
to Kamil Ziemian, golang-nuts
Note also, that you didn't paste the entire section:

With the exception of specific built-in functions, function and method calls and receive operations can appear in statement context. Such statements may be parenthesized. […] The following built-in functions are not permitted in statement context:

This is IMO very clear about those other examples being allowed.

Jason Phillips

unread,
Jul 28, 2023, 11:12:11 AM7/28/23
to golang-nuts
The confusion may come from the fact that a list of forbidden built-in operations is immediately followed by a list of (mostly) allowed operations that illustrate the original rule? With the exception of "len", it may be more clear for it to be structure like:
        ExpressionStmt = Expression .

        h(x+y)
        f.Close()
        <-ch
        (<-ch)
        len("foo") // illegal if len is the built-in function

    The following built-in functions are not permitted in statement context:
        append cap complex imag len make new real
        unsafe.Add unsafe.Alignof unsafe.Offsetof unsafe.Sizeof unsafe.Slice

But, that leaves the "len" example with zero context upfront.

Brian Candler

unread,
Jul 28, 2023, 11:32:03 AM7/28/23
to golang-nuts
If you wanted to be absolutely clear, you could insert "The following are examples of expression statements" - although it didn't really trouble me as-is.

Kamil Ziemian

unread,
Jul 29, 2023, 1:50:51 PM7/29/23
to Brian Candler, golang-nuts
"The confusion may come from the fact that a list of forbidden built-in operations is immediately followed by a list of (mostly) allowed operations that illustrate the original rule?"
You hit the nail on the head.

I don't have much faith in me as programmer, so I ask about any such issue that is bothering me.

Best regards,
Kamil

You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/xwavrjBZbeE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/e730ee30-0a9e-4be9-9fee-08ed73d32b89n%40googlegroups.com.

Kamil Ziemian

unread,
Aug 2, 2023, 12:59:06 PM8/2/23
to golang-nuts
Hello,

First, as I probably end my first reading of Go Spec in coming days, I want to thank you all for helping me in that. Thank you. :)

Second, I have question about example shown in section "Appending to and copying slices".

s0 := []int{0, 0}
s1 := append(s0, 2)                // append a single element     s1 == []int{0, 0, 2}
s2 := append(s1, 3, 5, 7)          // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
s3 := append(s2, s0...)            // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}
s4 := append(s3[3:6], s3[2:]...)   // append overlapping slice    s4 == []int{3, 5, 7, 2, 3, 5, 7, 0, 0}

I didn't understand why s4 looks that after append. I would guess that if I call append(s3[3:6], s3[:2]...) (s3[2:] replaced by s3[:2]) it should produce result above. But I don't think clearly recently, to much on my head.

Best regards,
Kamil

Brian Candler

unread,
Aug 2, 2023, 3:51:10 PM8/2/23
to golang-nuts
s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}

Therefore,
s3[3:6] is {3, 5, 7}   // from index 3 up to but not including 6
s3[2:] is {2, 3, 5, 7, 0, 0}  // from index 2 to end

Unless I'm missing something?

Axel Wagner

unread,
Aug 3, 2023, 12:49:39 AM8/3/23
to Brian Candler, golang-nuts
You're not missing anything. The example is correct and helpful. It's also something that can be tested out, for definite confirmation

Patrick Smith

unread,
Aug 3, 2023, 1:29:52 AM8/3/23
to Axel Wagner, Brian Candler, golang-nuts
Actually, this example is a bit unfortunate. Depending on the implementation of append, the capacity of s3 may be small enough that a new buffer must be allocated for s4, which means there is no need to test for overlaps. https://go.dev/play/p/n5FNqlA0DaS demonstrates that this is what happens in the current implementation, and also (x3 and x4) shows that overlaps are handled correctly when the existing buffer has enough capacity to be reused.

On Wed, Aug 2, 2023 at 9:49 PM 'Axel Wagner' via golang-nuts <golan...@googlegroups.com> wrote:
You're not missing anything. The example is correct and helpful. It's also something that can be tested out, for definite confirmation
Reply all
Reply to author
Forward
0 new messages