Generic function declarations

Function declarations … If the function declaration specifies type parameters, the function name denotes a generic function. A generic function must be instantiated before it can be called or used as a value. func min[T ~int|~float64](x, y T) T { if x < y { return x } return y } We’ve mentioned instantiation before, but it will be covered in depth later. For now, it’s enough to show an example of what the spec means can’t be done without instantiating a generic function:


Function declarations

No livestream today. My family is on vacation this week. I’ll be livestreaming again next week! Function declarations A function declaration binds an identifier, the function name, to a function. FunctionDecl = "func" FunctionName [ TypeParameters ] Signature [ FunctionBody ] . FunctionName = identifier . FunctionBody = Block . Nothing surprising here… So let’s move on to the first interesting rule: If the function’s signature declares result parameters, the function body’s statement list must end in a terminating statement.


No short declarations at package level

A couple last points about short variable declarations before we move on… Short variable declarations … Short variable declarations may appear only inside functions. In some contexts such as the initializers for “if”, “for”, or “switch” statements, they can be used to declare local temporary variables. So first: package foo id := 1 // Invalid. Short declarations only possible within fucntions var id = 1 // But this is valid. Don’t ask me why this rule exists.


Short variable declarations, cont'd

Today we’ll look at one of the most interesting, and I would say, confusing, aspects of short variable declarations. Short variable declarations … Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration.


Short variable declarations

Yesterday we saw how to define variables with var, but if you’ve ever actually used Go, you probably know that’s not actually the most common way to define variables. Let’s take a look at the alternative… Short variable declarations A short variable declaration uses the syntax: ShortVarDecl = IdentifierList ":=" ExpressionList . It is shorthand for a regular variable declaration with initializer expressions but no types: "var" IdentifierList "=" ExpressionList .


Unused variables

Variable declarations … Implementation restriction: A compiler may make it illegal to declare a variable inside a function body if the variable is never used. One short sentence. And people either love it, or hate it. I’m in the “love it” camp, but some people like the option to create unused variables, for later use, or during debugging. func foo() error { var i int // Some commented out code that probably used i // .


Declaring variable types

Today I’ll be love coding again. I hope you can join me! I’ll be working on the backlog for my open-source CouchDB SDK, https://kivik.io/. First some light refactoring, then adding a long-missing feature. Join me to see how many mistakes a senior Go dev makes while coding. We ended last week with a look at variable declarations. Today we continue that, with a look at how a variable’s type is determined.

Subscribe to Boldly Go: Daily

Every day I'll send you advice to improve your understanding of Go. Don't miss out! I will respect your inbox, and honor my privacy policy.

Unsure? Browse the archive.


Variable declarations

I don’t know about you, but I feel like we’ve just spent a month trudging through a dense jungle of generics details… let’s talk about something a bit more applicable to all of our code: Variable declarations A variable declaration creates one or more https://go.dev/ref/spec#Variables, binds corresponding identifiers to them, and gives each a type and an initial value. VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .


Go 1.21 has been released!

I’m a couple days late with the news… so you hopefully didn’t hear it here first. But two days ago, Go 1.21 was released. This means the Go spec has changed! Today I’ll highlight the main changes introduced to the spec in Go 1.21. None of the changes substantially impacts topics we’ve already covered in the spec series, so I won’t be going back to re-explain changed parts of the spec we’ve already covered.


Satisfying a type constraint

Satisfying a type constraint A type argument T satisfies a type constraint C if T is an element of the type set defined by C; i.e., if T implements C. As an exception, a strictly comparable type constraint may also be satisfied by a comparable (not necessarily strictly comparable) type argument. More precisely: A type T satisfies a constraint C if T implements C; or C can be written in the form interface{ comparable; E }, where E is a basic interface and T is comparable and implements E.


The comparable interface

Are you as curious about Fuzzing in Go as I am? On today’s live stream, I’ll be live coding my way through John Arundel’s 4-part series on Go Fuzzing. I hope you’ll join me! Today we’re learning about the predeclared comparable interface. But before this discussion makes sense, we should jump ahead to one key definition. That of the concept of “strictly comparable”: A type is strictly comparable if it is comparable and not an interface type nor composed of interface types.