Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Mastering Go

You're reading from   Mastering Go Create Golang production applications using network libraries, concurrency, machine learning, and advanced data structures

Arrow left icon
Product type Paperback
Published in Aug 2019
Publisher Packt
ISBN-13 9781838559335
Length 798 pages
Edition 2nd Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Mihalis Tsoukalos Mihalis Tsoukalos
Author Profile Icon Mihalis Tsoukalos
Mihalis Tsoukalos
Arrow right icon
View More author details
Toc

Table of Contents (15) Chapters Close

1. Go and the Operating System 2. Understanding Go Internals FREE CHAPTER 3. Working with Basic Go Data Types 4. The Uses of Composite Types 5. How to Enhance Go Code with Data Structures 6. What You Might Not Know About Go Packages and Functions 7. Reflection and Interfaces for All Seasons 8. Telling a UNIX System What to Do 9. Concurrency in Go – Goroutines, Channels, and Pipelines 10. Concurrency in Go – Advanced Topics 11. Code Testing, Optimization, and Profiling 12. The Foundations of Network Programming in Go 13. Network Programming – Building Your Own Servers and Clients 14. Machine Learning in Go 15. Other Books You May Enjoy

Getting user input

There are three main ways to get user input: firstly, by reading the command-line arguments of a program; secondly, by asking the user for input; or thirdly, by reading external files. This section will present the first two ways. Should you wish to learn how to read an external file, you should visit Chapter 8, Telling a UNIX System What to Do.

About := and =

Before continuing, it will be very useful to talk about the use of := and how it differs from =. The official name for := is the short assignment statement. The short assignment statement can be used in place of a var declaration with an implicit type.

You will rarely see the use of var in Go; the var keyword is mostly used for declaring global variables in Go programs, as well as for declaring variables without an initial value. The reason for the former is that every statement that exists outside of the code of a function must begin with a keyword such as func or var. This means that the short assignment statement cannot be used outside of a function because it is not available there.

The := operator works as follows:

m := 123 

The result of the preceding statement is a new integer variable named m with a value of 123.

However, if you try to use := on an already declared variable, the compilation will fail with the following error message, which makes perfect sense:

$ go run test.go
# command-line-arguments
./test.go:5:4: no new variables on left side of :=
  

So, you might now ask, what will happen if you are expecting two or more values from a function and you want to use an existing variable for one of them. Should you use := or =? The answer is simple: you should use :=, as in the following code example:

i, k := 3, 4 
j, k := 1, 2 

As the j variable is used for the first time in the second statement, you use := even though k has already been defined in the first statement.

Although it may seem boring to talk about such insignificant things, knowing them will save you from various types of errors in the long run!

Reading from standard input

The reading of data from the standard input will be illustrated in stdIN.go, which you will see in two parts. The first part is as follows:

package main 
 
import ( 
    "bufio" 
    "fmt" 
    "os" 
) 

In the preceding code, you can see the use of the bufio package for the first time in this book.

You will learn more about the bufio package in Chapter 8, Telling a UNIX System What to Do.

Although the bufio package is mostly used for file input and output, you will keep seeing the os package all the time in this book because it contains many handy functions; its most common functionality is that it provides a way to access the command-line arguments of a Go program (os.Args).

The official description of the os package tells us that it offers functions that perform OS operations. This includes functions for creating, deleting, and renaming files and directories, as well as functions for learning the UNIX permissions and other characteristics of files and directories. The main advantage of the os package is that it is platform independent. Put simply, its functions will work on both UNIX and Microsoft Windows machines.

The second part of stdIN.go contains the following Go code:

func main() {
var f *os.File f = os.Stdin defer f.Close() scanner := bufio.NewScanner(f) for scanner.Scan() { fmt.Println(">", scanner.Text()) } }

First, there is a call to bufio.NewScanner() using standard input (os.Stdin) as its parameter. This call returns a bufio.Scanner variable, which is used with the Scan() function for reading from os.Stdin line by line. Each line that is read is printed on the screen before getting the next one. Please note that each line that is printed by the program begins with the > character.

The execution of stdIN.go will produce the following kind of output:

$ go run stdIN.go
This is number 21
> This is number 21
This is Mihalis
> This is Mihalis
Hello Go!
> Hello Go!
Press Control + D on a new line to end this program!
> Press Control + D on a new line to end this program!
  

According to the UNIX way, you can tell a program to stop reading data from standard input by pressing Ctrl + D.

The Go code of stdIN.go and stdOUT.go will be very useful when we talk about UNIX pipes in Chapter 8, Telling a UNIX System What to Do, so do not underestimate their simplicity.

Working with command-line arguments

The technique of this section will be illustrated using the Go code of cla.go, which will be presented in three parts. The program will find the minimum and the maximum of its command-line arguments.

The first part of the program is as follows:

package main 
 
import ( 
    "fmt" 
    "os" 
    "strconv" 
) 

What is important here is realizing that getting the command-line arguments requires the use of the os package. Additionally, you need another package, named strconv, in order to be able to convert a command-line argument, which is given as a string, into an arithmetical data type.

The second part of the program is the following:

func main() { 
    if len(os.Args) == 1 { 
        fmt.Println("Please give one or more floats.") 
        os.Exit(1) 
    } 
 
    arguments := os.Args 
    min, _ := strconv.ParseFloat(arguments[1], 64) 
    max, _ := strconv.ParseFloat(arguments[1], 64) 

Here, cla.go checks whether you have any command-line arguments by checking the length of os.Args. This is because the program needs at least one command-line argument to operate. Please note that os.Args is a Go slice with string values. The first element in the slice is the name of the executable program. Therefore, in order to initialize the min and max variables, you will need to use the second element of the string type os.Args slice that has an index value of 1.

There is an important point here: the fact that you are expecting one or more floats does not necessarily mean that the user will give you valid floats, either by accident or on purpose. However, as we have not talked about error handling in Go so far, cla.go assumes that all command-line arguments are in the right format and therefore will be acceptable. As a result, cla.go ignores the error value returned by the strconv.ParseFloat() function using the following statement:

n, _ := strconv.ParseFloat(arguments[i], 64) 

The preceding statement tells Go that you only want to get the first value returned by strconv.ParseFloat() and that you are not interested in the second value, which in this case is an error variable, by assigning it to the underscore character. The underscore character, which is called blank identifier, is the Go way of discarding a value. If a Go function returns multiple values, you can use the blank identifier multiple times.

Ignoring all or some of the return values of a Go function, especially the error values, is a very dangerous technique that should not be used in production code!

The third part comes with the following Go code:

    for i := 2; i < len(arguments); i++ { 
        n, _ := strconv.ParseFloat(arguments[i], 64) 
 
        if n < min { 
            min = n 
        } 
        if n > max { 
            max = n 
        } 
    } 
 
    fmt.Println("Min:", min) 
    fmt.Println("Max:", max) 
} 

Here, you use a for loop that will help you to visit all the elements of the os.Args slice, which was previously assigned to the arguments variable.

Executing cla.go will create the following kind of output:

$ go run cla.go -10 0 1
Min: -10
Max: 1
$ go run cla.go -10
Min: -10
Max: -10
  

As you might expect, the program does not behave well when it receives erroneous input; the worst thing of all is that it does not generate any warnings to inform the user that there was an error (or several) while processing the command-line arguments of the program:

$ go run cla.go a b c 10
Min: 0
Max: 10
  
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime