Introduction to the
In the previous module, you configured a Go environment for creating and running programs written in Go. In addition, you will learn the basic coding structure of the Go program and how to compile and run the application.
In this module, you will step through the basic data types provided by Go and use functions to organize code written in.go files. You will also learn how to manage and write programs in different files under the same package. Finally, you’ll learn how to create and use packages in Go.
Learning goals
In this module you will:
- Declare variables and constants
- Understand the basic data types that Go provides
- Write a function
- Create and use packages
A prerequisite for
- A Go environment for creating applications
- Ability to create and modify.go files
- Ability to run Go applications using a terminal
Declare and use variables
That variable
To declare a variable, use the var keyword:
var firstName string
Copy the code
The previous statement declares a variable of type string called firstName. (We’ll discuss data types in a later section.) This example demonstrates the most basic way to declare a variable. To declare other variables, simply add a similar statement to the previous one. But if two variables are of the same type, you can declare multiple variables in a single line:
var firstName, lastName string
Copy the code
By adding a comma (,) after the variable name, you indicate that you are going to declare other variables. In this case, the previous statement declares two variables of type string: firstName and lastName. To add a third variable of type int, write the code as follows:
var firstName, lastName string
var age int
Copy the code
Another way to write the previous statement is to use parentheses after the var keyword, like declaring variables through a special block, as follows:
var (
firstName, lastName string
age int
)
Copy the code
Initialize a variable
At this point, you can only declare variables, but sometimes you need to give them initial values. In Go, you can initialize variables in a number of ways. For example, following the same example mentioned earlier, you can initialize each variable with this code:
var (
firstName string = "John"
lastName string = "Doe"
age int = 32
)
Copy the code
If you decide to initialize a variable, you don’t need to specify its type, because when you initialize the variable with a specific value, Go will infer its type. For example, you can declare and initialize variables in this way:
var (
firstName = "John"
lastName = "Doe"
age = 32
)
Copy the code
Go will infer that the variables firstName and lastName are of type string and that the variable age is of type int.
Initialize variables in a number of ways
In Go, you can declare and initialize variables in a single line. Separate each variable name with a comma, and perform the same operations (in the same order) on each value, as follows:
var (
firstName, lastName, age = "John"."Doe".32
)
Copy the code
There is another way to declare and initialize variables. This method is the most common way to do this in Go. Here’s the same example we used:
func main(a) {
firstName, lastName := "John"."Doe"
age := 32
println(firstName, lastName, age)
}
Copy the code
Run the code above to verify that this method can declare and initialize variables.
Note that after you define the variable name, you need to put a colon equals sign (:=) and the corresponding value here. When the colon equals sign is used, the variable to be declared must be new. If the colon equals sign is used and the variable has been declared, the program will not compile. Keep trying.
Finally, you can use the colon equals sign inside the function. When declaring variables outside a function, you must do this using the var keyword. If you’re not familiar with functions, don’t worry. We’ll cover functions in a future unit.
Declare constants
Sometimes you need to include static values in your code, called constants. Go supports the use of constants. The keyword used to declare a constant is const.
For example, you can declare constants as follows:
const HTTPStatusOK = 200
Copy the code
Like variables, Go can infer a type from the value assigned to a constant. In Go, constant names are usually written in mixed uppercase or all uppercase letters.
If you need to declare multiple constants in a block, do as follows:
const (
StatusOK = 0
StatusConnectionReset = 1
StatusOtherError = 2
)
Copy the code
Note: Go defines an interesting concept for constants, ioTA, which is not further explained in this module. But you can check out the Go Wiki on GitHub for more information. Remember that IOTA is a keyword; Go can use this keyword to simplify constant definitions if there is an order for these values.
There are similarities and some important differences between constants and variables. For example, you can declare constants without using them. You will not receive error messages. You cannot declare constants using a colon equals sign. If you do this, Go will issue a warning.
If a variable is declared but not used, Go throws an error
The important thing to remember is that in Go, when you declare a variable but don’t use it, Go throws an error, rather than a warning as some other programming languages do.
For example, let’s go back to one of the examples mentioned earlier and remove the println call:
func main(a) {
firstName, lastName := "John"."Doe"
age := 32
}
Copy the code
You will see the following error message:
./main.go:4:2: firstName declared but not used
./main.go:4:13: lastName declared but not used
./main.go:5:2: age declared but not used
Copy the code
Remember, for every variable declared in Go, you have to use it somewhere.
Understand basic data types
Go is a strongly typed language. This means that each variable you declare is bound to a specific data type and only accepts values that match that type.
Go has four types of data:
- Basic types: numbers, strings, and Booleans
- Aggregate types: arrays and structures
- Reference types: pointer, slice, map, function, and channel
- Interface type: interface
In this module, we cover only basic types. Don’t worry if you don’t know what the other types are. We will cover this in a subsequent module.
First, let’s look at the data types of values.
An integer number
In general, the key that defines integer types is int. But Go also provides the int8, INT16, INT32, and INT64 types, which are integers of 8, 16, 32, or 64 bits, respectively. When you only use int, the size is 32 bits on 32-bit systems and 64 bits on 64-bit systems (most of the time, though it may vary from computer to computer). If you need to represent a value as an unsigned number, you can use uint, but only if there is a specific reason for using this type. In addition, Go provides the uint8, Uint16, uint32, and uint64 types.
The following example demonstrates how to use various integer types in Go:
var integer8 int8 = 127
var integer16 int16 = 32767
var integer32 int32 = 2147483647
var integer64 int64 = 9223372036854775807
println(integer8, integer16, integer32, integer64)
Copy the code
For the most part, you’ll use int, but you’ll need to know about the other integer types, because in Go, int is different from INT32, even if integers have a natural size of 32 bits. In other words, when you need a cast, you need an explicit cast. If you try to perform mathematical operations between different types, you will get an error. For example, suppose you have the following code:
var integer16 int16 = 127
var integer32 int32 = 32767
println(integer16 + integer32)
Copy the code
When you run the program, you receive the following error:
invalid operation: integer16 + integer32 (mismatched types int16 and int32)
Copy the code
As you can see, unlike other programming languages, you need to perform explicit operations when converting a value from one type to another in Go. We will discuss how to cast types properly at the end of this module.
As you learn to Go, you may receive information about runes. Rune is simply an alias for the int32 data type. It is used to represent Unicode characters (or Unicode code points). For example, suppose you have the following code:
rune: ='G'
println(rune)
Copy the code
When you run the previous code snippet, you might see the program printer G at the command prompt. However, you will also see the number 71, which represents the Unicode character for G. We’ll cover Runes in more detail in a future module.
You can see the scope of each type by looking at the Go source code. Knowing the range of each type will help you choose the right data type and avoid hotting up bits in memory.
Challenge 1: Set another variable of type int and use the value in the integer32 or integer64 variable to confirm the natural size of the variable on the system. If you are on a 32-bit system and use a value greater than 2,147,483,647, the following overflow error occurs: constant 9223372036854775807 Overflows int
Question solution:
package main
func main(a) {
var integer32 int = 2147483648
println(integer32)
}
Copy the code
Challenge 2: Declare an unsigned variable (like uint) and initialize it with a negative value (like -10). An error occurs when you try to run the program: constant-10 overflows uint.
Question solution:
package main
func main(a) {
var integer uint = - 10
println(integer)
}
Copy the code
Floating point Numbers
Go provides two floating-point size data types: FLOAT32 and float64. If you need to store large numbers, you can use these types, which do not fit into any of the previously mentioned integer types. The difference between the two types is the maximum number of bits they can hold. See the following lines to see how these two types are used:
var float32 float32 = 2147483647
var float64 float64 = 9223372036854775807
println(float32.float64)
Copy the code
You can use the math.MaxFloat32 and math.MaxFloat64 constants provided with the Math package to find these two types of limits. Print the maximum floating point value in the command prompt with the following code:
package main
import "math"
func main(a) {
println(math.MaxFloat32, math.MaxFloat64)
}
Copy the code
Floating point types are also useful when decimal numbers are needed. For example, you could write something like this:
const e = 2.71828
const Avogadro = 6.02214129 electronics
const Planck = 6.62606957 e-34
Copy the code
Notice that, as in the previous code, Go infer its data type from the values used.
The Boolean
Boolean types can have only two values: true and false. You can declare a Boolean type using the keyword bool. Go differs from other programming languages in that you cannot implicitly convert a Boolean type to 0 or 1. You must do this explicitly.
Therefore, you can declare a Boolean variable as follows:
var featureFlag bool = true
Copy the code
When we discuss control flow statements in Go, we will use Boolean data types in subsequent modules. We will also use these types in future modules.
string
Finally, let’s look at the most common data type in programming languages: string. In Go, the keyword string is used to represent the string data type. To initialize a string variable, you define the value in double quotes (“). Single quotes (‘) are used for single characters (and runes, as we described in the previous section).
For example, the following code demonstrates two ways to declare and initialize a string variable:
var firstName string = "John"
lastName := "Doe"
println(firstName, lastName)
Copy the code
Sometimes, you need to escape characters. To do this, use a backslash (\) before the character in Go. For example, here are the most common examples of escaped characters:
- \ n: new line
- \r: Carriage return
- \ T: TAB
- ‘: single quotation mark
- “: double quotation marks
- \ : Backslash
Use the following code snippet to test escape characters:
fullName := "John Doe \t(alias \"Foo\")\n"
println(fullName)
Copy the code
You should see the following output (including new lines) :
John Doe (alias "Foo")
Copy the code
The default value
So far, almost every time a variable is declared, it is initialized with its value. But unlike in other programming languages, in Go, all data types have default values if you don’t initialize variables. This feature is handy because you don’t have to check if the variable is initialized before using it.
Here are a few defaults for the types we’ve explored so far:
int
Type 0 (and all subtypes, such as INT64)float32
和float64
Types of + 0.000000 e+000bool
Types of falsestring
The null value of the
Run the following code snippet to confirm the defaults listed earlier:
var defaultInt int
var defaultFloat32 float32
var defaultFloat64 float64
var defaultBool bool
var defaultString string
println(defaultInt, defaultBool, defaultFloat32, defaultFloat64, defaultString)
Copy the code
You can use code similar to this code to determine the default values for data types that we did not browse to.
Type conversion
In the previous section, we confirmed that implicit casts do not work in Go. Next, an explicit cast is required. Go provides native methods for converting one data type to another. For example, one approach is to use built-in functions for each type, as follows:
var integer16 int16 = 127
var integer32 int32 = 32767
println(int32(integer16) + integer32)
Copy the code
Another way to convert Go is to use the Strconv package. For example, to convert a string to an int, use the following code, and vice versa:
package main
import "strconv"
func main(a) {
i, _ := strconv.Atoi("- 42")
s := strconv.Itoa(- 42)
println(i, s)
}
Copy the code
Run the previous code and confirm that it runs and print -42 twice.
Notice that in the previous code, there was an underscore (_) used as the name of the variable. In Go, this means that we do not use the value of the variable, but ignore it. Otherwise, the program will not compile because we need to use all the declared variables. We’ll return to this topic, and you’ll see what _ usually means in a subsequent module.
Create a function
In Go, functions allow you to group together a set of statements that can be called from other parts of your application. Instead of creating programs that contain many statements, you can use functions to organize your code and make it easier to read. More readable code is also easier to maintain.
So far, we’ve been calling the println() function and writing code inside the main() function. In this section, we’ll explore how to create custom functions. We will also introduce some other techniques that can be used with the Go function.
The main function
The function that interacts with it is the main() function. All executable programs in Go have this function because it is the starting point of the program. You can only have one main() function in your program. If you are creating a Go package, you do not need to write the main() function. We will cover how to create packages in a future module.
Before diving into the basics of how to create custom functions, let’s look at one important feature of the main() function. You may have noticed that the main() function takes no arguments and returns nothing. But that doesn’t mean it can’t read values from the user, such as command-line arguments. To access command-line arguments in Go, you can perform operations using the OS package and os.args variables that hold all the arguments passed to the program.
The following code reads two numbers from the command line and sums them:
package main
import (
"os"
"strconv"
)
func main(a) {
number1, _ := strconv.Atoi(os.Args[1])
number2, _ := strconv.Atoi(os.Args[2])
println("Sum:", number1+number2)
}
Copy the code
The os.args variable contains each command line argument passed to the program. Since these values are of type String, they need to be converted to int for summation.
To run the program, use the following command:
go run main.go 3 5
Copy the code
The output is as follows:
Sum: 8
Copy the code
Let’s see how to refactor the above code and create our first custom function.
Custom function
Here is the syntax for creating functions:
func name(parameters) (results) {
body-content
}
Copy the code
Note that the func keyword is used to define the function and then give it a name. After naming, specify the argument list for the function. You can specify zero or more parameters. You can also define the return type of a function, which can be zero or more. (We’ll discuss how to return multiple values in the next section). After defining all these values, you can write the body of the function.
To practice this technique, we’ll refactor the code from the previous section to sum the numbers in our custom function. We will use the following code:
package main
import (
"os"
"strconv"
)
func main(a) {
sum := sum(os.Args[1], os.Args[2])
println("Sum:", sum)
}
func sum(number1 string, number2 string) int {
int1, _ := strconv.Atoi(number1)
int2, _ := strconv.Atoi(number2)
return int1 + int2
}
Copy the code
This code creates a function called sum that takes two string arguments, casts them to int, and returns the sum. When you define a return type, the function needs to return the value of that type.
In Go, you can also set a name for the return value of a function, treating it as a variable. For example, you could refactor the sum function as follows:
func sum(number1 string, number2 string) (result int) {
int1, _ := strconv.Atoi(number1)
int2, _ := strconv.Atoi(number2)
result = int1 + int2
return
}
Copy the code
Note that you now need to enclose the result value of the function in parentheses. You can also use this variable in functions and simply add the return line at the end. Go will return the current values of these return variables. Writing the return keyword at the end of a function is easy and convenient, especially if there are multiple return values. We don’t recommend this approach, however, because it’s not very clear what the function returns.
Return multiple values
In Go, functions can return multiple values. You can define these values in a similar way to how you define function parameters. In other words, you can specify a type and a name, but the name is optional.
For example, suppose you want to create a function that sums two numbers and then multiplies them. The function code will look like this:
func calc(number1 string, number2 string) (sum int, mul int) {
int1, _ := strconv.Atoi(number1)
int2, _ := strconv.Atoi(number2)
sum = int1 + int2
mul = int1 * int2
return
}
Copy the code
You now need two variables to store the result of the function. (Otherwise it will not compile.) It looks like this:
func main(a) {
sum, mul := calc(os.Args[1], os.Args[2])
println("Sum:", sum)
println("Mul:", mul)
}
Copy the code
Another interesting feature of Go is that if a return value of a function is not needed, the function can be discarded by assigning the return value to the _ variable. The _ variable is the idiomatic way that Go ignores the return value. It allows the program to compile. Therefore, if only and is required, the following code can be used:
func main(a) {
sum, _ := calc(os.Args[1], os.Args[2])
println("Sum:", sum)
}
Copy the code
We’ll detail how to ignore the return value of a function when we explore error handling in a later module.
Changing function parameter values (Pointers)
When a value is passed to a function, each change in that function does not affect the caller. Go is a “pass by value” programming language. This means that every time a value is passed to a function, Go uses that value and creates a local copy (a new variable in memory). Any changes you make to this variable in the function will not affect the changes you send to the function.
For example, suppose you created a function to update people’s names. Notice what happens when you run this code:
package main
func main(a) {
firstName := "John"
updateName(firstName)
println(firstName)
}
func updateName(name string) {
name = "David"
}
Copy the code
Even if you change the name to David in the function, the output is still John. Since changes in the updateName function only modify the local copy, the output does not change. Go passes the value of a variable, not the variable itself.
If you want to make changes in updateName that affect the firstName variable in main, use Pointers. A pointer is a variable that contains the memory address of another variable. When you send a pointer to a function, you don’t pass a value, you pass address memory. Therefore, every change made to this variable affects the caller.
In Go, there are two operators that can be used to handle Pointers:
- The & operator uses the address of the object that follows.
- The * operator dereferences the pointer. That is, you can go to the address contained in the pointer to access the object within it.
Let’s modify the previous example to illustrate how Pointers work:
package main
func main(a) {
firstName := "John"
updateName(&firstName)
println(firstName)
}
func updateName(name *string) {
*name = "David"
}
Copy the code
Run the previous code. Notice that the output now shows David, not John.
The first thing to do is change the function’s signature to indicate that you want to receive Pointers. To do this, change the parameter type from String to *string. (The latter is still a string, but it is now a pointer to a string.) Then, when assigning a new value to the variable, you add an asterisk (*) to the left of the variable to pause its value. When updateName is called, the system does not send the value, but the memory address of the variable. This is why the previous code has an ampersand to the left of the variable.
Understand the package
Go packages are similar to libraries or modules in other programming languages. You can package the code and reuse it in other places. The source code for the package can be distributed in multiple.go files. So far, we’ve written the main package and made some references to other local packages.
In this section, you will learn what a package is. You’ll also learn how to create a package and how to use external packages.
The main package
You may have noticed that in Go, even the most straightforward programs are part of a package. Typically, the default package is the main package, which is the package you’ve been using so far. If the program is part of the main package, Go generates binaries. When the file is run, it calls the main() function.
In other words, when you use the main package, the program generates separate executables. But Go does not generate binaries when the program is not part of the main package. It generates package archive files (files with an extension of.a).
By convention, the package name is the same as the last element of the import path. For example, to import the Math/RAND package, import it as follows:
import "math/rand"
Copy the code
To reference an object in a package, do the following:
rand.Int()
Copy the code
Let’s create the package.
Create a package
Create a new directory in the $GOPATH/ SRC directory named Calculator. Create a file named sum.go. The tree directory should look like the following:
src/
calculator/
sum.go
Copy the code
Initialize the sum.go file with the package name:
package calculator
Copy the code
You can now start writing the package’s functions and variables. Unlike other programming languages, Go does not provide the public or private keywords to indicate whether variables or functions can be called from inside or outside the package. But Go follows two simple rules:
- If you want to make something special, start with a lowercase letter.
- If you want to make something public, start with a capital letter.
Next, let’s add the following code to the calculator package we want to create:
package calculator
var logMessage = "[LOG]"
// Version of the calculator
var Version = "1.0"
func internalSum(number int) int {
return number - 1
}
// Sum two integer numbers
func Sum(number1, number2 int) int {
return number1 + number2
}
Copy the code
Let’s take a look at some things in this code:
- Can only be called from within a package
logMessage
The variable. - It can be accessed from any location
Version
The variable. It is recommended that you add comments describing the purpose of this variable. (This description applies to any user of the package.) - Can only be called from within a package
internalSum
Function. - It can be accessed from any location
Sum
Function. It is recommended that you add a comment describing the purpose of this function. - To confirm that everything is working, run it in the Calculator directory
go build
Command. If you do this, be aware that the system does not generate executable binaries.
Create a module
Calculator functionality has been incorporated into the package. Packages can now be combined into modules. Why is that? The module of the package specifies the context that Go needs to run the combined code. This context information includes the version of Go used when the code was written.
In addition, modules help other developers refer to specific versions of code and work with dependencies more easily. Another advantage is that our program source doesn’t have to be strictly in the $GOPATH/ SRC directory. If this restriction is released, it makes it easier to use different package versions together in other projects.
Therefore, to create a module for the Calculator package, run the following command in the root directory ($GOPATH/ SRC/Calculator) :
go mod init github.com/myuser/calculator
Copy the code
After running this command, github.com/myuser/calculator becomes the name of the package. In other programs, you will use that name for reference. The command also creates a new file called go.mod. Finally, the tree directory will now look like the following:
src/
calculator/
go.mod
sum.go
Copy the code
The go.mod content of this file should look like this: (Go versions may vary.)
module github.com/myuser/calculator
go 1.14
Copy the code
To reference this package in another program, you need to import it using the module name. In this case, the name is called github.com/myuser/calculator. Now, let’s take a look at an example to see how to use this package.
Note: In the past, managing dependencies in Go was not easy. The dependency management system is still a work in progress. If you want to know the detailed information about the module, please [see] Go blog (https://blog.golang.org/using-go-modules) in the series of posts.
Referencing local packages (modules)
Now, let’s use packages first. We’ll stick with the sample application we’ve been using. This time, we’ll use the function we created earlier in the Calculator package, instead of the sum function in the main package.
The tree file structure should now look like this:
src/
calculator/
go.mod
sum.go
helloworld/
main.go
Copy the code
We will use this code for $GOPATH/SRC/helloworld/main go file:
package main
import "github.com/myuser/calculator"
func main(a) {
total := calculator.Sum(3.5)
println(total)
println("Version: ", calculator.Version)
}
Copy the code
Notice that the import statement uses the name of the package created: Calculator. To call Sum from this package, you specify calculator.sum as the package name. Finally, you now have access to the Version variable. Press to invoke the following: Calculator.version.
If you try to run the program immediately, it will do nothing. You need to inform Go that you will use modules to reference other packages. To do this, run the following command in the $GOPATH/ SRC /helloworld directory:
go mod init helloworld
Copy the code
In the above command, HelloWorld is the project name. This command creates a new go.mod file, so the tree directory will look like this:
src/
calculator/
go.mod
sum.go
helloworld/
go.mod
main.go
Copy the code
If you open the go.mod file, you should see something similar to the following: (Go versions may vary.)
The module helloworld go 1.14Copy the code
Since you are referencing a local copy of the module, you need to tell Go not to use remote locations. Therefore, you need to manually modify the go.mod file to include references as follows:
Module helloworld go 1.14 the require github.com/myuser/calculator v0.0.0 replace github.com/myuser/calculator. = >. /calculatorCopy the code
The replace keyword specifies that the local directory is used instead of the remote location of the module. In this case, since the HelloWorld and Calculator programs are in $GOPATH/ SRC, the location can only be.. / the calculator. If the module source is in a different location, define the local path here.
Run the program with the following command:
go run main.go
Copy the code
The system should output the following information:
8
Version: 1.0
Copy the code
Challenge 1: What happens if you try to call the logMessage variable or internalSum function from the Calculator package in the main application? Is it running? Give it a try!
Question solution:
package main
import "github.com/myuser/calculator"
func main(a) {
total := calculator.internalSum(5)
println(total)
println("Version: ", calculator.logMessage)
}
Copy the code
Publish a package
You can easily release the Go package. Simply expose the source code of the supplied package. Most developers use GitHub to publicly distribute packages. This is why references to github.com are sometimes found in import statements.
For example, if you want to publish the Calculator package to the GitHub account, you need to create a repository called Calculator. The URL should be similar to the following:
https://github.com/myuser/calculator
Copy the code
You will version the package by marking the repository as follows:
Git tag v0.1.0 Git push Origin v0.1.0Copy the code
If it’s a developer (including yourself) who wants to use your package, quote the following:
import "github.com/myuser/calculator"
Copy the code
Let’s discuss how to reference third-party packages in more detail.
Reference external (third party) packages
Sometimes, programs need to reference packages written by other developers. You can usually find these packages on GitHub. Whether you want to develop a package (not the main package) or a standalone program (the main package), the following instructions for referencing third-party packages apply.
Let’s add a reference to the rsc. IO /quote package:
package main
import (
"github.com/myuser/calculator"
"rsc.io/quote"
)
func main(a) {
total := calculator.Sum(3.5)
println(total)
println("Version: ", calculator.Version)
println(quote.Hello())
}
Copy the code
If Visual Studio Code is used, the go.mod file will be updated when the file is saved. It now looks like this:
1.14 the require module helloworld go (github.com/myuser/calculator v0.0.0 RSC. IO/quote v1.5.2) to replace github.com/myuser/calculator => .. /calculatorCopy the code
Note how rsc. IO /quote refers to a particular package version. If you need to upgrade your program’s dependencies, you need to change the version here.
Run the program again using the following command:
go run main.go
Copy the code
The output should look like this:
8
Version: 1.0
Hello, world.
Copy the code
All future references to third-party packages need to be included in the go.mod file. When an application is run or compiled, Go downloads all of its dependencies.
conclusion
We covered the basics you need to start building more complex applications in Go. Now, you can declare and initialize variables in several ways. You also know about the various data types that Go provides. You’ve used the most basic data types,
You also learned how to create functions to organize your code and make it easier to maintain. As you already know, Go is a “pass-by-value” language, but it also supports Pointers. We will use Pointers in a later part of the module.
Finally, you’ve seen how packages work in Go and how to create modules when you need to share code with other developers. As you’ve already seen, if you only need to create a standalone application, all your code needs to be part of the main package. As you’ve already seen, the starting point for this program is the main() function. You now know how to reference local and third-party modules. You will use these modules when building the Go application.
The next section,
(3) Use control flow in Go
Article source: www.sdk.cn/details/wAK…