Go Concepts - Lexical Structure: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
No edit summary
 
(51 intermediate revisions by the same user not shown)
Line 1: Line 1:
=Internal=
=TO DEPLETE=
 
<font color=darkkhaki>
* [[Go Concepts#Subjects|Concepts]]


=Source Files=
=Source Files=
Line 7: Line 6:
Go code goes into source files. They have the <tt>.go</tt> extension.  
Go code goes into source files. They have the <tt>.go</tt> extension.  


Each source file is mandatory declared to belong to a [[Go Concepts - Packages#Overview|package]].
Each source file is mandatory declared to belong to a [[Go_Language_Modularization#Overview|package]].


They can then optionally import code from other packages, using the <tt>[[Go Keyword import|import]]</tt> keyword.
They can then optionally import code from other packages, using the <tt>[[Go Keyword import|import]]</tt> keyword.
Line 14: Line 13:


Thera are no restrictions on the file name, it is not required to have any relationship with the name of the package it contains code for.
Thera are no restrictions on the file name, it is not required to have any relationship with the name of the package it contains code for.
=Comments=
<pre>
// to the end of the line
</pre>
<pre>
/*
  Multiline
  line 1
  ...
  line n
*/
</pre>
=Whitespace=
Whitespace in Go are carriage returns (u+000D), newlines (u+000A), spaces (u+0020) and tabs (u+0009).


=Semicolons=
=Semicolons=
Line 54: Line 34:
A block is a sequence of declarations and statements within matching curly braces. The block may be empty. The most common blocks are those defined in the source code - they define block lexical scopes (see [[#Variable_Scopes|variable scopes]]). Aside from those, Go recognizes the following implicit blocks:
A block is a sequence of declarations and statements within matching curly braces. The block may be empty. The most common blocks are those defined in the source code - they define block lexical scopes (see [[#Variable_Scopes|variable scopes]]). Aside from those, Go recognizes the following implicit blocks:
* The ''universe block'' which contains all Go source text.
* The ''universe block'' which contains all Go source text.
* The [[Go Concepts - Packages#Package_Block|package block]].
* The [[Go_Language_Modularization#Package_Block|package block]].
* The ''file block'' that contains all the [[#Source_Files|source text in the file]].
* The ''file block'' that contains all the [[#Source_Files|source text in the file]].
* Each <tt>if</tt>, <tt>[[Go for|for]]</tt> and <tt>switch</tt> statements is considered to be in its own implicit block.
* Each <tt>if</tt>, <tt>[[Go for|for]]</tt> and <tt>switch</tt> statements is considered to be in its own implicit block.
Line 61: Line 41:
=Identifiers=
=Identifiers=


''Identifiers'' name program entities, such as [[#Constants|constants]], [[#Variables|variables]], [[Go_Concepts_-_The_Type_System#Built-in_Types|types]], functions, [[Go Concepts - Packages#Package_Names|packages]], etc. An identifier is a sequence of one more letter and digits. The first character must be a letter. The letters are unicode letters or underscore "_". It must not be a [[#Keywords|keyword]], keywords are reserved by the language.
''Identifiers'' name program entities, such as [[#Constants|constants]], [[#Variables|variables]], [[Go_Concepts_-_The_Type_System#Built-in_Types|types]], functions, [[Go_Language_Modularization#Package_Names|packages]], etc. An identifier is a sequence of one more letter and digits. The first character must be a letter. The letters are unicode letters or underscore "_". It must not be a [[#Keywords|keyword]], keywords are reserved by the language.


Identifiers can be exported, and the way the first letter is capitalized is relevant to whether the identifier is exported or not. See [[Go Concepts - Packages#Exported_Identifiers|exported identifiers]].
Identifiers can be exported, and the way the first letter is capitalized is relevant to whether the identifier is exported or not. See [[Go_Language_Modularization#Exported_Identifiers|exported identifiers]].


It is idiomatic to use camel case style for Go identifiers.
It is idiomatic to use camel case style for Go identifiers.
==Pre-Declared Identifiers==
Pre-declared identifiers are available by default, without needing to import anything. They are implicitly declared in the ''universe block''.
Pre-declared '''types''': <tt>[[Go Booleans#Overview|bool]]</tt>, <tt>[[Go Integers#Overview|byte]]</tt>, <tt>[[Go Floating-Point Numbers#Overview|complex64]]</tt>, <tt>[[Go Floating-Point Numbers#Overview|complex128]]</tt>, <tt>[[Go Floating-Point Numbers#Overview|float32]]</tt>, <tt>[[Go Floating-Point Numbers#Overview|float64]]</tt>, <tt>[[Go Integers#Overview|int]]</tt>, <tt>[[Go Integers#Overview|int8]]</tt>, <tt>[[Go Integers#Overview|int16]]</tt>, <tt>[[Go Integers#Overview|int32]]</tt>, <tt>[[Go Integers#Overview|int64]]</tt>, <tt>[[Go Integers#Overview|rune]]</tt>, <tt>[[Go Strings#Overview|string]]</tt>, <tt>[[Go Integers#Overview|uint]]</tt>, <tt>[[Go Integers#Overview|uint8]]</tt>, <tt>[[Go Integers#Overview|uint16]]</tt>, <tt>[[Go Integers#Overview|uint32]]</tt>, <tt>[[Go Integers#Overview|uint64]]</tt>, <tt>[[Go Integers#Overview|uintptr]]</tt> and <tt>[[Go error Type|error]]</tt>.
Pre-declared '''constants''':  <tt>[[Go Booleans#Boolean_Literals|true]]</tt>, <tt>[[Go Booleans#Boolean_Literals|false]]</tt>, <tt>[[Go iota|iota]]</tt>.
Pre-declared '''functions''':  <tt>[[Go Slices#append.28.29|append]]</tt>, <tt>[[Go Built-In Functions Length and Capacity#cap.28.29|cap]]</tt>, <tt>[[Go Built-In Function close|close]]</tt>, <tt>[[Go Built-In Functions for Manipulating Complex Numbers#complex.28.29|complex]]</tt>, <tt>[[Go Slices#copy.28.29|copy]]</tt>, <tt>[[Go Maps#delete.28.29|delete]]</tt>, <tt>[[Go Built-In Functions for Manipulating Complex Numbers#imag.28.29|imag]]</tt>, <tt>[[Go Built-In Functions Length and Capacity#len.28.29|len]]</tt>, <tt>[[Go Built-In Function make|make]]</tt>, <tt>[[Go Built-In Function new|new]]</tt>, <tt>[[Go Concepts - Error Handling#Panics|panic]]</tt>, <tt>[[go Built-In Functions for Bootstrapping#print.28.29|print]]</tt>, <tt>[[go Built-In Functions for Bootstrapping#println.28.29|println]]</tt>, <tt>[[Go Built-In Functions for Manipulating Complex Numbers#real.28.29|real]]</tt>, <tt>[[Go Concepts - Error Handling#Panics|recover]]</tt>. Also see [[Go Concepts - Functions#Built-in_Functions|built-in functions]].
Pre-declared zero value: <tt>nil</tt>.
==The Blank Identifier==
"_" is the blank identifier. The blank identifier is used to tell the compiler that we don't need the variable.


==Exported Identifiers==
==Exported Identifiers==


<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
:[[Go_Concepts_-_Packages#Exported_Identifiers|Exported Identifiers]]
:[[Go_Language_Modularization#Exported_Identifiers|Exported Identifiers]]
</blockquote>
</blockquote>


==Keywords==
==Keywords==
The language had reserves a set of ''keywords'' that cannot be used as identifiers.
<blockquote style="background-color: AliceBlue; border: solid thin LightSteelBlue;">
:https://golang.org/ref/spec#Keywords<br>
</blockquote>
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
:{|
:{|
| <tt>break</tt> || <tt>default</tt> || <tt>[[go Keyword func|func]]</tt> || <tt>[[Go_Interfaces#Declaration|interface]]</tt> || <tt>select</tt>
| <tt>break</tt> || <tt>default</tt> || <tt>[[go Keyword func|func]]</tt> ||  || <tt>[[Go_Channels#select|select]]</tt>
|-
|-
|  <tt>case</tt> || <tt>[[Go_Concepts_-_Functions#defer|defer]]</tt> || <tt>[[Go_Concepts_-_Concurrency#Goroutine|go]]</tt> || <tt>[[Go Maps#Long_Declaration|map]]</tt> || <tt>[[Go Structs|struct]]</tt>
|  <tt>case</tt> || <tt>[[Go_Concepts_-_Functions#defer|defer]]</tt> || <tt>go</tt> || <tt>[[Go Maps#Long_Declaration|map]]</tt> || <tt>[[Go Structs|struct]]</tt>
|-
|-
| <tt>[[Go_Concepts_-_Concurrency#Channels|chan]]</tt> || <tt>else</tt> || <tt>goto</tt>|| <tt>[[Go Concepts - Packages#The_package_keyword|package]]</tt> || <tt>switch</tt>
| <tt>[[Go_Channels|chan]]</tt> || <tt>else</tt> || <tt>goto</tt>|| <tt>[[Go_Language_Modularization#The_package_keyword|package]]</tt> || <tt>switch</tt>
|-
|-
| <tt>[[#Constants|const]]</tt> || <tt>fallthrough</tt> || <tt>[[Go if|if]]</tt> || <tt>[[go Keyword range|range]]</tt> || <tt>[[Go_Concepts_-_The_Type_System#User-Defined_Types|type]]</tt>
| <tt>[[#Constants|const]]</tt> || <tt>fallthrough</tt> || <tt>if</tt> || || <tt>[[Go_Concepts_-_The_Type_System#User-Defined_Types|type]]</tt>
|-
|-
| <tt>continue</tt> || <tt>[[Go for|for]]</tt> || <tt>[[go Keyword import|import]]</tt> || <tt>return</tt> || <tt>[[#Variables|var]]</tt>
| <tt>continue</tt> || <tt>[[Go for|for]]</tt> || <tt>[[go Keyword import|import]]</tt> || <tt>return</tt> || <tt>[[#Variables|var]]</tt>
Line 113: Line 70:
=Literals=
=Literals=


A ''literal'' is a notation for representing a fixed value in source code. Go provides literals for [[Go Booleans#Boolean_Literals|booleans]], [[Go Integers#Integer_Literals|integers]], [[Go Floating-Point Numbers#Floating-Point_Literals|floating-point values]], [[Go Strings#String_Literals|strings]], built-in types such as [[Go Arrays#Array_Literals|arrays]], [[Go Slices#Slice_Literals|slices]] and [[Go Maps#Map_Literals|maps]], user-defined types ([[Go Structs#Struct_Literals|structs]]), [[Go Concepts - Functions#Function_Literals|functions]], etc. The compiler is always able to infer the literal's type.
A ''literal'' is a notation for representing a fixed value in source code. Go provides literals for [[Go Booleans#Boolean_Literals|booleans]], [[Go Integers#Integer_Literals|integers]], [[Go Floating Point#Floating-Point_Literals|floating-point values]], [[Go Strings#String_Literals|strings]], built-in types such as [[Go Arrays#Array_Literals|arrays]], [[Go Slices#Slice_Literals|slices]] and [[Go Maps#Map_Literals|maps]], user-defined types ([[Go Structs#Struct_Literals|structs]]), [[Go Concepts - Functions#Function_Literals|functions]], etc. The compiler is always able to infer the literal's type.


=Declarations=
=Declarations=
Line 130: Line 87:


* https://golang.org/ref/spec#Variable_declarations
* https://golang.org/ref/spec#Variable_declarations
This is the idiomatic way to specify we want a variable initialized with its zero value. If the variable is initialized to something else than the zero value, the [[#Short_Variable_Declaration|short variable declaration]] should be used.


<pre>
<pre>
Line 148: Line 107:


Assigning a value is optional, if no value is explicitly assigned, the variable is initialized to the type's [[Go Concepts - The Type System#Zero_Value|zero value]]. However, the type must be specified in this case.
Assigning a value is optional, if no value is explicitly assigned, the variable is initialized to the type's [[Go Concepts - The Type System#Zero_Value|zero value]]. However, the type must be specified in this case.
Multiple variables are declared as such:
<pre>
var (
    a = 1
    b = 2
    c = "something"
)
</pre>


===Short Variable Declaration===
===Short Variable Declaration===
Line 153: Line 122:
* https://golang.org/ref/spec#Short_variable_declarations
* https://golang.org/ref/spec#Short_variable_declarations


Another form of variable declaration that ''always'' assigns an initial value and also ''infers'' the variable type based on the literal type is the following:
The short variable declaration uses the short variable declaration operator (<tt>[[Go_Concepts_-_Operators#:.3D|:=]]</tt>). It ''implies'' a variable declaration (<tt>var</tt>) so it cannot be used for variable that have been already declared. It ''always'' assigns an initial value and also ''infers'' the variable type based on the literal type, so there is no need to declare the variable's type. The short variable declaration is the idiomatic way to declare variables that must be initialized to values other than the zero value. To initialize variables to their zero values, use the [[#Long_Variable_Declaration|long variable declaration]].


<pre>
<pre>
<variable_identifier> := <initial_value_literal>
<variable_identifier> := <initial_value_literal>
</pre>
</pre>
The compiler uses the type of the right hand expression to infer the type of the variable being declared.


Example:
Example:
Line 165: Line 136:
</pre>
</pre>


This syntax can be used in a [[Go for|for]] loop. Note that this form cannot be used for the declaration of a [[#Package-Level_Variable|package-level variable]].
This syntax can be used in a [[Go for|for]] loop.  
 
Note that this form cannot be used for the declaration of [[#Package-Level_Variable|package-level variable]]. These are other example where the short variable declaration does not work:
 
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
:[[Go Short Variable Declaration Invalid Cases|Short Variable Declaration Invalid Cases]]
</blockquote>
 
===When to use the Long and when to use the Short Declaration===


Generally, the shorter value should be used whenever possible. Some books claim that the long value is not "idiomatic". For more details on variable names, see [[#Identifiers|identifiers]].
Generally, the shorter value should be used whenever possible. Some sources claim that the long value is not "idiomatic".  


Multiple variables are declared as such:
Other sources suggest to use the long form when declaring variables that will be initialized to their zero value and to use the short form when providing extra initialization or making a function call.


<pre>
For more details on variable names, see [[#Identifiers|identifiers]].
var (
    a = 1
    b = 2
    c = "something"
)
</pre>


==Variable Scopes==
==Variable Scopes==
Line 191: Line 164:
===Package-Level Variable===
===Package-Level Variable===


An unexported variable declared at the package level (outside any function) is visible throughout the package.
A package-level variable is a variable declared outside the scope of any function.
 
An unexported variable declared at the package level (outside any function) is only visible throughout the package.


An [[Go_Concepts_-_Packages#Exported_Identifiers|exported variable]] declared at the package level is visible throughout the package and in all packages that import the exporting package.
An [[Go_Language_Modularization#Exported_Identifiers|exported variable]] declared at the package level is visible throughout the package and in all packages that import the exporting package.


===Functions and Variable Scopes===
===Functions and Variable Scopes===
Line 201: Line 176:
</blockquote>
</blockquote>


==Pass by Value vs Pass by Reference==
==Pointers==
 
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
:[[Go_Concepts_-_Functions#Pass_by_Value_vs._Pass_by_Reference|Pass by value vs. pass by reference]]
</blockquote>


==Pointers==
A ''pointer variable'' or a ''pointer'' is a [[Go_Concepts_-_The_Type_System#Pointer_Types|pointer type]] variable. It contains an address to a memory location. Pointers are not commonly used with [[Go_Concepts_-_The_Type_System#Built-in_Types|built-in types]], but are very useful when paired with structs.


A ''pointer'' is a [[Go_Concepts_-_The_Type_System#Pointer_Types|pointer type]] variable. It contains an address to a memory location. Pointers are not commonly used with [[Go_Concepts_-_The_Type_System#Built-in_Types|built-in types]], but are very useful when paired with structs.
Pointers are useful when functions need to access and change state of a variable that was declared within the scope of a different function and possibly a different goroutine. It is convenient, but also dangerous if the variable is modified concurrently without mutual exclusion protection.


In absence of explicit initialization, pointer are initialized to <tt>nil</tt>.
In absence of explicit initialization, pointer are initialized to <tt>nil</tt>.


===Reference and Dereference Operators===
On a 64-bit architecture, a pointer variable requires 8 bytes of memory.
 
<tt>[[Go_Concepts_-_Operators#.26|&]]</tt> the reference operator - returns a [[Go_Concepts_-_The_Type_System#Pointer_Types|pointer type]] instance which contains the address in memory for the value of the given variable. <tt>&</tt> should be read as "address of ..."
 
<tt>[[Go_Concepts_-_Operators#.2A|*]]</tt> the dereference operator - gives access to the value at the memory location indicated by the pointer contained by the given variable. The variable must contain a [[Go_Concepts_-_The_Type_System#Pointer_Types|pointer type]] instance, otherwise the compiler will complain. The value thus exposed can be read or written.
 
<pre>
var i
var ptri *int
 
// pointer to the memory location containing i
ptri = &i
 
// value the pointer is pointing to
var j = *ptri
 
// i == j
</pre>
 
=Constants=
 
Constants are [[#Variables|variables]] whose values cannot be changed once declared. The compiler detects modification attempts and throws a compilation error.
 
==Constant Declarations==
 
The declaration syntax is similar to that used to declare variables:
 
<pre>
const <constant_identifier> <constant_type_literal> = <initial_value_literal>
</pre>
 
Example:
<pre>
const a string = "something"
const b = 1
</pre>
 
As with variables, the type can be omitted, as it can be inferred.
 
Multiple constants are declared as such:
 
<pre>
const (
    a = 1
    b = 2
    c = "something"
)
</pre>
 
=Statements=
 
* Go Language Specification https://golang.org/ref/spec#Statements
 
Statements control execution flow within a [[Go Concepts - Functions#Function_Definition|function]].
 
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
:{|
| <tt>[[Go for|for]]</tt> ||    || <tt>[[Go if|if]]</tt> ||
|}
</blockquote>
 
=Expressions=
 
[[Go Concepts - Operators|Operators]] combine operands into [[#Expression|expressions]].
 
=Types=
 
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
:[[Go Concepts - The Type System|The Type System]]
</blockquote>
 
=Functions=
 
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
:[[Go Concepts - Functions|Functions]]
</blockquote>
 
=Operators=
 
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
:[[Go Concepts - Operators|Operators]]
</blockquote>

Latest revision as of 22:46, 6 September 2023

TO DEPLETE

Source Files

Go code goes into source files. They have the .go extension.

Each source file is mandatory declared to belong to a package.

They can then optionally import code from other packages, using the import keyword.

Each source file has its own file block.

Thera are no restrictions on the file name, it is not required to have any relationship with the name of the package it contains code for.

Semicolons

Go programs may omit most of the semicolons at the end of line if the following conditions apply:

  1. When the input is broken into tokens, a semicolon is automatically inserted into the token stream immediately after a line's final token if that token is:
    1. an identifier
    2. an integer, floating-point, imaginary, rune, or string literal
    3. one of the keywords break, continue, fall through, or return
    4. one of the operators and delimiters ++, --, ), ], or }
  2. To allow complex statements to occupy a single line, a semicolon may be omitted before a closing ")" or "}".

For more details, see the specification:

https://golang.org/ref/spec#Semicolons

Blocks

A block is a sequence of declarations and statements within matching curly braces. The block may be empty. The most common blocks are those defined in the source code - they define block lexical scopes (see variable scopes). Aside from those, Go recognizes the following implicit blocks:

  • The universe block which contains all Go source text.
  • The package block.
  • The file block that contains all the source text in the file.
  • Each if, for and switch statements is considered to be in its own implicit block.
  • Each clause in a switch and select statements acts as an implicit block.

Identifiers

Identifiers name program entities, such as constants, variables, types, functions, packages, etc. An identifier is a sequence of one more letter and digits. The first character must be a letter. The letters are unicode letters or underscore "_". It must not be a keyword, keywords are reserved by the language.

Identifiers can be exported, and the way the first letter is capitalized is relevant to whether the identifier is exported or not. See exported identifiers.

It is idiomatic to use camel case style for Go identifiers.

Exported Identifiers

Exported Identifiers

Keywords

break default func select
case defer go map struct
chan else goto package switch
const fallthrough if type
continue for import return var

Literals

A literal is a notation for representing a fixed value in source code. Go provides literals for booleans, integers, floating-point values, strings, built-in types such as arrays, slices and maps, user-defined types (structs), functions, etc. The compiler is always able to infer the literal's type.

Declarations

A declaration binds an identifier to a constant, type, variable, function, label or package. Every identifier in the program must be declared. No identifier may be declared twice in the same block, and no identifier may be declared in both the file and package block.

Variables

A variable is a storage location in memory. Go being a statically typed language, a variable always has a specific type. A variable also has a name, which is referred to as variable identifier.

The Go compiler will generate an error if a variable is declared and not used.

Variable Declarations

Long Variable Declaration

This is the idiomatic way to specify we want a variable initialized with its zero value. If the variable is initialized to something else than the zero value, the short variable declaration should be used.

var <variable_identifier> <variable_type_literal> = <initial_value_literal>

Example:

var a string = "blue"
var b = "red"
var c string
var f = func (i int) int {
        return i
}

Declaring the type is optional if an initial value is specified, the compiler is able to infer the type of the literal, and the variable will be built to have that type.

Assigning a value is optional, if no value is explicitly assigned, the variable is initialized to the type's zero value. However, the type must be specified in this case.

Multiple variables are declared as such:

var (
     a = 1
     b = 2
     c = "something"
)

Short Variable Declaration

The short variable declaration uses the short variable declaration operator (:=). It implies a variable declaration (var) so it cannot be used for variable that have been already declared. It always assigns an initial value and also infers the variable type based on the literal type, so there is no need to declare the variable's type. The short variable declaration is the idiomatic way to declare variables that must be initialized to values other than the zero value. To initialize variables to their zero values, use the long variable declaration.

<variable_identifier> := <initial_value_literal>

The compiler uses the type of the right hand expression to infer the type of the variable being declared.

Example:

a := "blah"

This syntax can be used in a for loop.

Note that this form cannot be used for the declaration of package-level variable. These are other example where the short variable declaration does not work:

Short Variable Declaration Invalid Cases

When to use the Long and when to use the Short Declaration

Generally, the shorter value should be used whenever possible. Some sources claim that the long value is not "idiomatic".

Other sources suggest to use the long form when declaring variables that will be initialized to their zero value and to use the short form when providing extra initialization or making a function call.

For more details on variable names, see identifiers.

Variable Scopes

The range of places where a variable is visible from it is called the scope of the variable.

Go is lexically scoped using blocks.

A variable is visible within the block delimited by the nearest curly braces {}, but not outside them. The variable is visible inside any sub-blocks.

If a variable with the same name is defined in a sub-block, the that variable takes precedence, in the sub-block and its sub-blocks, over the variable declared in the upper block.

Package-Level Variable

A package-level variable is a variable declared outside the scope of any function.

An unexported variable declared at the package level (outside any function) is only visible throughout the package.

An exported variable declared at the package level is visible throughout the package and in all packages that import the exporting package.

Functions and Variable Scopes

Functions and Variable Scopes

Pointers

A pointer variable or a pointer is a pointer type variable. It contains an address to a memory location. Pointers are not commonly used with built-in types, but are very useful when paired with structs.

Pointers are useful when functions need to access and change state of a variable that was declared within the scope of a different function and possibly a different goroutine. It is convenient, but also dangerous if the variable is modified concurrently without mutual exclusion protection.

In absence of explicit initialization, pointer are initialized to nil.

On a 64-bit architecture, a pointer variable requires 8 bytes of memory.