Movatterモバイル変換


[0]ホーム

URL:


Packt
Search iconClose icon
Search icon CANCEL
Subscription
0
Cart icon
Your Cart(0 item)
Close icon
You have no products in your basket yet
Save more on your purchases!discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Profile icon
Account
Close icon

Change country

Modal Close icon
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timerSALE ENDS IN
0Days
:
00Hours
:
00Minutes
:
00Seconds
Home> Programming> Programming Language> Go Programming - From Beginner to Professional
Go Programming - From Beginner to Professional
Go Programming - From Beginner to Professional

Go Programming - From Beginner to Professional: Learn everything you need to build modern software using Go , Second Edition

Arrow left icon
Profile Icon Samantha Coyle
Arrow right icon
Mex$664.99Mex$738.99
Full star iconFull star iconFull star iconFull star iconHalf star icon4.8(11 Ratings)
eBookMar 2024680 pages2nd Edition
eBook
Mex$664.99 Mex$738.99
Paperback
Mex$922.99
Subscription
Free Trial
Arrow left icon
Profile Icon Samantha Coyle
Arrow right icon
Mex$664.99Mex$738.99
Full star iconFull star iconFull star iconFull star iconHalf star icon4.8(11 Ratings)
eBookMar 2024680 pages2nd Edition
eBook
Mex$664.99 Mex$738.99
Paperback
Mex$922.99
Subscription
Free Trial
eBook
Mex$664.99 Mex$738.99
Paperback
Mex$922.99
Subscription
Free Trial

What do you get with eBook?

Product feature iconInstant access to your Digital eBook purchase
Product feature icon Download this book inEPUB andPDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature iconDRM FREE - Read whenever, wherever and however you want
Product feature iconAI Assistant (beta) to help accelerate your learning
OR

Contact Details

Modal Close icon
Payment Processing...
tickCompleted

Billing Address

Table of content iconView table of contentsPreview book icon Preview Book

Go Programming - From Beginner to Professional

Variables and Operators

Overview

In this chapter, you will be introduced to various features of Go and gain a basic understanding of what Go code looks like. You will also be provided with a deep understanding of how variables work and will perform exercises and activities to get hands-on andget going.

By the end of this chapter, you will be able to use variables, packages, and functions in Go. You will also know how to change variable values in Go. Later in this chapter, you will use operators with numbers and design functionsusing pointers.

Technical requirements

For this chapter, you'll require Go version 1.21 or higher. The code for this chapter can be foundat:https://github.com/PacktPublishing/Go-Programming-From-Beginner-to-Professional-Second-Edition-/tree/main/Chapter01.

Introduction to Go

Go (or Golang, as it’s often called) is a programming language that’s popular with developers because of how rewarding it is to use to develop software. It’s also popular with companies because teams of all sizes can be productive with it. Go has also earned a reputation for consistently delivering software with exceptionallyhigh performance.

Go has an impressive pedigree since it was created by a team from Google with a long history of building great programming languages and operating systems. They created a language that has the feel of a dynamic language such as JavaScript or PHP but with the performance and efficiency of strongly typed languages such as C++ and Java. They wanted a language that was engaging for the programmer but practical in projects with hundredsof developers.

Go is packed with interesting and unique features, such as being compliant with memory safety and channel-based concurrency. We’ll explore these features in this chapter. By doing so, you’ll see that their unique implementation within Go is what makes Gotruly special.

Go is written in text files that are then compiled down to machine code and packaged into a single, standaloneexecutable file. The executable is self-contained, with nothing needed to be installed first to allow it to run. Having a single file makes deploying and distributing Go software hassle-free. When compiling, you can pick one of several target operating systems, including – but not limited to – Windows, Linux, macOS, and Android. With Go, you write your code once and run it anywhere. Complied languages fell out of favor because programmers hated long waits for their code to compile. The Go team knew this and built a lightning-fast compiler that remains fast asprojects grow.

Go has a statically typed and type-safe memory model with a garbage collector that automates memory management. This combination protects developers from creating many of the most common bugs and security flaws found in software while still providing excellent performance and efficiency. Dynamically typed languages such as Ruby and Python have become popular in part because programmers felt they could be more productive if they didn’t have to worry about types and memory. The downside of these languages is that they give up performance and memory efficiency and can be more prone to type-mismatch bugs. Go has the same levels of productivity as dynamically typed languages while not giving up performanceand efficiency.

A massive shift in computer performance has taken place. Going fast now means you need to be able to do as much work parallel or concurrently as possible. This change is due to the design of modern CPUs, which emphasize more cores over high clock speed. None of the currently popular programming languages have been designed to take advantage of this fact, which makes writing parallel and concurrent code in them error-prone. Go is designed to take advantage of multiple CPU cores, and it removes all the frustration and bug-filled code. Go is designed to allow any developer to easily and safely write parallel and concurrent code that enables them to take advantage of modern multicore CPUs and cloud computing – unlocking high-performance processing and massive scalability withoutthe drama.

What does Go look like?

Let’s take our first look at some Go code. This code randomly prints a message to the console from a pre-defined listof messages:

package main// Import extra functionality from packagesimport (  "errors"  "fmt"  "log"  "math/rand"  "strconv"  "time")// Taken from: https://en.wiktionary.org/wiki/Hello_World#Translationsvar helloList = []string{  "Hello, world",  "Καλημέρα κόσμε",  "こんにちは世界",  "سلام دنیا‎",  "Привет, мир",}

Themain() function is definedas follows:

func main() {  // Seed random number generator using the current time  rand.NewSource(time.Now().UnixNano())  // Generate a random number in the range of out list  index := rand.Intn(len(helloList))  // Call a function and receive multiple return values  msg, err := hello(index)  // Handle any errors  if err != nil {    log.Fatal(err)  }  // Print our message to the console  fmt.Println(msg)}

Let’s consider thehello() function:

func hello(index int) (string, error) {  if index < 0 || index > len(helloList)-1 {    // Create an error, convert the int type to a string    return "", errors.New("out of range: " + strconv.Itoa(index))  }  return helloList[index], nil}

Now, let’s step through this code pieceby piece.

At the top of our script isthe following:

package main

This code is our package declaration. All Go files must start with one of these. If you want to run the code directly, you’ll need to name itmain. If you don’t name itmain, then you can use it as a library and import it into other Go code. When creating an importable package, you can give it any name. All Go files in the same directory are considered part of the same package, which means all the files must have the samepackage name.

In the following code, we’re importing codefrom packages:

// Import extra functionality from packagesimport (  "errors"  "fmt"  "log"  "math/rand"  "strconv"  "time")

In this example, the packages are all from Go’s standard library. Go’s standard library is very high-quality and comprehensive. It’s strongly recommended that you maximize your use of it. You can tell if a package isn’t from the standard library because it’ll look like a URL – forexample,github.com/fatih/color.

Go has a module system that makes using external packages easy. To use a new module, add it to your import path. Go will automatically download it for you the next time youbuild code.

Imports only apply to the file they’re declared in, which means you must declare the same imports over and over in the same package and project. But fear not – you don’t need to do this by hand. There are many tools and Go editors that automatically add and remove the importsfor you:

// Taken from: https://en.wiktionary.org/wiki/Hello_World#Translationsvar helloList = []string{  "Hello, world",  "Καλημέρα κόσμε",  "こんにちは世界",  "سلام دنیا‎",  "Привет, мир",}

Here, we’re declaring a global variable, which is a list of strings, and initializing it with data. The text or strings in Go support multi-byte UFT-8 encoding, making them safe for any language. The type of list we’re usinghere is called a slice. There are three types of lists in Go: slices, arrays, and maps. All three are collections of keys and values, where you use the key to get avalue from the collection. Slice and array collections use a number as the key. The first key is always 0 in slices and arrays. Also, in slices and arrays, the numbers are contiguous, which means there is never a break in the sequence of numbers. With themap type, you get to choose thekey type. You use this when you want to use some other data to look up the value in the map. For example, you could use a book’s ISBN to look up its titleand author:

func main() {…}

Here, we’re declaring a function. A function is some code that runs when called. You can pass data in the form of one or more variables to a function and optionally receive one or more variables back from it. Themain() function in Go is special. Themain() function is the entry point of your Go code. There may only be onemain() function within themain package. When your code runs, Go automatically callsmain to getthings started:

  // Seed random number generator using the current time  rand.Seed(time.Now().UnixNano())  // Generate a random number in the range of out list  index := rand.Intn(len(helloList))

In the preceding code, we are generating a random number. The first thing we need to do is ensure it’s a good random number; to do that, we mustseed the random number generator. We seed it using the current time formatted to a Unix timestamp with nanoseconds. To get the time, we call theNow function in thetime package. TheNow function returns a struct type variable. Structs are a collection of properties and functions, a little like objects in other languages. In this case, we are calling theUnixNano function on that struct straight away. TheUnixNano function returns a variable of theint64 type, which is a 64-bit integer or, more simply, a number. This number is passed intorand.Seed. Therand.Seed function accepts anint64 variable as its input. Note that the type of the variable fromtime.UnixNano andrand.Seed must be thesame. With that, we’ve successfully seeded the randomnumber generator.

What we want is a number we can use to get a random message. We’ll userand.Intn for this job. This function gives us a random number between 0 and 1, minus the number we pass in. This may sound a bit strange, but it works out perfectly for what we’re trying to do. This is because our list is a slice where the keys start from 0 and increment by 1 for each value. This means the last index is 1 less than the length ofthe slice.

To show you what this means, here is somesimple code:

package mainimport (  "fmt")func main() {  helloList := []string{    "Hello, world",    "Καλημέρα κόσμε",    "こんにちは世界",    "سلام دنیا‎",    "Привет, мир",  }  fmt.Println(len(helloList))  fmt.Println(helloList[len(helloList)-1])  fmt.Println(helloList[len(helloList)])}

This code prints the length of the listand then uses that length to print the last element. To do that, we must subtract 1; otherwise, we’d get an error, which is what the lastline causes:

Figure 1.1: Output displaying an error

Figure 1.1: Output displaying an error

Once we’ve generated our random number, we assign it to a variable. We do this with the short variable declaration seen with the:= notation, which is a very popular shortcut in Go within a function. It tells the compiler to go ahead and assign that value to the variable and select the appropriate type for that value implicitly. This shortcut is one of the many things that makes Go feel like a dynamicallytyped language:

  // Call a function and receive multiple return values  msg, err := hello(index)

Then, we use that variable to call a function namedhello. We’ll look athello in just a moment. The important thing to note is that we’re receiving two values back from the function and we’re able to assign them to two new variables,msg anderr, using the:= notation and witherr as thesecond value:

func hello(index int) (string, error) {…}

This code is the definition of thehello function; we’re not showing the body for now. A function acts as a unit of logic that’s called when and as often as is needed. When calling a function, the code that calls it stops running and waits for the function to finish running. Functions are a great tool for keeping your code organized and understandable. In the signature ofhello, we’ve defined that it accepts a singleint value and that it returns astring value and anerror value. Havingerror as your last return value is a very common thing to have in Go. The code between{} is the body of the function. Thefollowing code is what’s run when thefunction’s called:

  if index < 0 || index > len(helloList)-1 {    // Create an error, convert the int type to a string    return "", errors.New("out of range: " + strconv.Itoa(index))  }  return helloList[index], nil

Here, we are inside the function; the first line of the body is anif statement. Anif statement runs the code inside its{} if its Boolean expression is true. The Boolean expression is the logic betweenif and{. In this case, we’re testing to see if the passedindex variable is less than 0 or greater than the largest possible sliceindex key.

If the Boolean expression were to be true, then our code would return an emptystring and anerror value. At this point, the function would stop running, and the code that called the function would continue to run. If the Boolean expression were not true, its code would be skipped over, and our function would return a value fromhelloList andnil. In Go,nil represents something with no value andno type:

  // Handle any errors  if err != nil {    log.Fatal(err)  }

After we’ve runhello, the first thing we need to do is check if it ran successfully. We can do this by checking theerror value stored inerr. Iferr is not equal tonil, then we know we have an error. You will see checks on whethererr is not equal tonil as opposed to checks on whethererr is equal tonil, as this simplifies the checks and logic for the code base. In the case of an error, we calllog.Fatal, which writes out a logging message and kills ourapp. Once the app’s been killed, no morecode runs:

  // Print our message to the console  fmt.Println(msg)

If there is no error, then we know thathello ran successfully and that the value ofmsg can be trusted to hold a valid value. The final thing we need to do is print the message to the screen viathe Terminal.

Here’s howthat looks:

Figure 1.2: Output displaying valid values

Figure 1.2: Output displaying valid values

In this simple Go program, we’ve been able to cover a lot of key concepts that we’ll explore in full in thecoming chapters.

Exercise 1.01 – using variables, packages, and functions to print stars

In this exercise, we’ll use some of what we learned about in the preceding example to print a random number, between 1 and 5, of stars (*) to the console. This exercise will give you a feel of whatworking with Go is like and some practice with using the features of Go we’ll need going forward. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Now, add the imports we’ll useinthis file:
    import (  "fmt"  "math/rand"  "strings"  "time")
  4. Create amain() function:
    func main() {
  5. Seed the randomnumber generator:
      rand.Seed(time.Now().UnixNano())
  6. Generate a random number between 0 and then add 1 to get a numberbetween 1and 5:
      r := rand.Intn(5) + 1
  7. Use the string repeater tocreate a string with the number ofstarswe need:
      stars := strings.Repeat("*", r)
  8. Print the string with the stars to the console with a new line character at the end and close themain() function:
      fmt.Println(stars)}
  9. Save the file. Then, in the new folder, runthe following:
    go run .

The following isthe output:

Figure 1.3: Output displaying stars

Figure 1.3: Output displaying stars

In this exercise, we created a runnable Go program by defining themain package with amain() function in it. We used the standard library by adding imports to packages. Thosepackages helped us generate a randomnumber, repeat strings, and write tothe console.

Activity 1.01 – defining and printing

In this activity, we are going to create a medical form for a doctor’s office to capture a patient’s name, age, and whether they have apeanut allergy:

  1. Create a variable forthe following:
    1. First name asa string.
    2. Family name asa string.
    3. Age as anint value.
    4. Peanut allergy as abool value.
  2. Ensure they have aninitial value.
  3. Print the values tothe console.

The following is theexpected output:

Figure 1.4: Expected output after assigning the variables

Figure 1.4: Expected output after assigning the variables

Note

The solution to all activities in this chapter can be found in the GitHub repositoryhere:https://github.com/PacktPublishing/Go-Programming-From-Beginner-to-Professional-Second-Edition-/tree/main/Chapter01

Next, we’ll start going into detail about what we’ve covered so far, so don’t worry if you are confused or have anyquestions about whatyou’ve seenso far.

Declaring variables

Now that you’ve had a glimpse of Go and completed your first exercise, we’re going to dive deep. Our first stop on our journeyis variables.

A variable holds data foryou temporarily so that you can work with it. When you declare a variable, it needs four things: a statement that you are declaring a variable, a name for the variable, the type of data it can hold, and an initial value for it. Fortunately, some of the parts are optional, but that also means there’s more than one way of defininga variable.

Let’s cover all the ways you can declarea variable.

Declaring a variable using var

Usingvar is the foundational way todeclare a variable. Every other way we’ll cover is a variation of this approach, typically by omitting parts of this definition. A fullvar definition with everything in place lookslike this:

var foo string = "bar"

The key parts arevar,foo,string, and= "bar":

  • var is our declaration that we are defininga variable
  • foo is the name ofthe variable
  • string is the type ofthe variable
  • = "bar" is itsinitial value

Exercise 1.02 – declaring a variable using var

In this exercise, we’ll declare twovariables using the fullvar notation. Then, we’ll printthem to the console. You’ll see that you can use thevar notation anywhere in your code, which isn’t true for all variable declaration notations. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add the main package name to the top ofthe file:
    package main
  3. Addthe imports:
    import (  "fmt")
  4. Declare a variable at the package-level scope. We’ll cover what scopes are indetail later:
    var foo string = "bar"
  5. Create themain() function:
    func main() {
  6. Declare another variable usingvar inour function:
      var baz string = "qux"
  7. Print both variables tothe console:
      fmt.Println(foo, baz)
  8. Close themain() function:
    }
  9. Save the file. Then, in the new folder, runthe following:
    go run .

The following isthe output:

bar qux

In this example,foo is declared at the package level whilebaz is declared at the function level. Where a variable is declared is important because where you declare a variable also limits what notation you can use todeclare it.

Next, we’ll look at another way to use thevar notation.

Declaring multiple variables at once with var

We can use a singlevar declaration to define more than one variable using avar block or statement. Using this method is commonwhen declaring package-level variables. The variables don’t need to be of the same type, and they can all have their own initial values. The notation lookslike this:

var (  <name1> <type1> = <value1>  <name2> <type2> = <value2>…  <nameN> <typeN> = <valueN>)

You can have multiple of these types of declarations. This is a nice way to group related variables, thereby making your code more readable. You can use this notation in functions, but it’s rare to see itused there.

Exercise 1.03 – declaring multiple variables at once with var

In this exercise, we’ll declare multiplevariables using onevar statement, each with a different type and initial value. Then, we’ll print the value of each variable to the console. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Addthe imports:
    import (  "fmt"  "time")
  4. Start thevar declaration:
    var (
  5. Definethree variables:
      Debug   bool   = false  LogLevel  string  = "info"  startUpTime time.Time = time.Now()
  6. Close thevar declaration:
    )
  7. In themain() function, printeach variable tothe console:
    func main() {  fmt.Println(Debug, LogLevel, startUpTime)}
  8. Save the file. Then, in the new folder, runthefollowing:
    go run.

    The following isthe output:

Figure 1.5: Output displaying three variable values

Figure 1.5: Output displaying three variable values

In this exercise, we declared three variables using a singlevar statement. Your output will look different for thetime.Time variable, but that’s correct. The format is the same, but the time itselfis different.

Using thevar notation like this is a good way to keep your code well organized and save yousome typing.

Next, we’ll start removing someof the optional parts of thevar notation.

Skipping the type or value when declaring variables

In real-world code, it’s not common to use the fullvar notation. There are a few cases where you need to define a package-level variable with an initial value and tightly control its type. In those cases, youneed the full notation. It’ll be obvious when this is needed as you’ll have a type mismatch of some kind, so don’t worry too much about this for now. The rest of the time, you’ll remove an optional part or use the shortvariable declaration.

You don’t need to include both the type and the initial value when declaring a variable. You can use just one or the other; Go works out the rest. If you have a type in the declaration but no initial value, Go uses the zero value for the type you picked. We’ll talk about what a zero value is later in this book. On the other hand, if you have an initial value and no type, Go has a ruleset for how to infer the types that are needed from the literal valueyou use.

Exercise 1.04 – skipping the type or value when declaring variables

In this exercise, we’ll update our previous exercise so that it skips the optional initial values or type declarations from our variable declaration. Then, we’ll print the values to the console, as we did previously, to show that the result is the same. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import (  "fmt"  "time")
  4. Start themulti-variable declaration:
    var (
  5. Thebool value in the first exercise has an initial value of false. That’s abool value’s zero value, so we’ll drop the initial value from its declaration as it is setby default:
      Debug   bool
  6. The next two variables both have a non-zero value for their type, so we’ll drop theirtype declaration:
      LogLevel  = "info"  startUpTime = time.Now()
  7. Close thevar declaration:
    )
  8. In themain() function, print outeach variable:
    func main() {  fmt.Println(Debug, LogLevel, startUpTime)}
  9. Save the file. Then, in the new folder, runthe following:
    go run .

    The following isthe output:

Figure 1.6: Output displaying variable values despite not mentioning the type while declaring the variables

Figure 1.6: Output displaying variable values despite not mentioning the type while declaring the variables

In this exercise, we were able to update the previous code so that it uses a much more compact variable declaration. Declaring variables is something you’ll have to do a lot, and not having to use the notation makes for a better experience whenwriting code.

Next, we’ll look at a situation where you can’t skip any ofthe parts.

Type inference gone wrong

There are times when you’ll need to use all the parts of the declaration – for example, when Go isn’t able to guess the correct type you need. Let’stake a look at an exampleof this:

package mainimport "math/rand"func main() {  var seed = 1234456789  rand.NewSource(seed)}

The following isthe output:

Figure 1.7: Output showing an error

Figure 1.7: Output showing an error

The issue here is thatrand.NewSource requires a variable of theint64 type. Go’s type inference rules interoperate a whole number, such as the one we used as anint value. We’ll look at the difference between them in more detail later in this book. To resolve this, we will addint64 type to the declaration. Here’s howthat looks:

package mainimport "math/rand"func main() {  var seed int64 = 1234456789  rand.NewSource(seed)}

Next, we’ll look at aneven quicker way todeclare variables.

Short variable declaration

When declaring variables in functions and functions only, we can use the:= shorthand. This shorthand allows us to make our declarations even shorter. It does this by allowing us to not have to use thevar keyword and by always inferring thetype from a requiredinitial value.

Exercise 1.05 – implementing a short variable declaration

In this exercise, we’ll update ourprevious exercise so that it uses a short variable declaration. Since you can only use a short variable declaration in a function, we’ll move our variable out of the package scope. Where beforeDebug had a type but no initial value, we’ll switch it back so that it has an initial value since that’s required when using a short variable declaration. Finally, we’ll print it to the console. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import (  "fmt"  "time")
  4. Create themain() function:
    func main() {
  5. Declare each variable using the short variabledeclaration notation:
      Debug := false  LogLevel := "info"  startUpTime := time.Now()
  6. Print the variables tothe console:
      fmt.Println(Debug, LogLevel, startUpTime)}
  7. Save the file. Then, inthe new folder, runthe following:
    go run .

The following isthe output:

Figure 1.8: Output displaying the variable values that were printed after using short variable declaration notation

Figure 1.8: Output displaying the variable values that were printed after using short variable declaration notation

In this exercise, we updated our previous code to use a very compact way to declare variables when we have an initial valueto use.

The:= shorthand is very popular with Go developers and the most common way in which variables get defined in real-world Go code. Developers like how it makes their code concise and compact while still being clear as towhat’s happening.

Another shortcut is declaring multiple variables on thesame line.

Declaring multiple variables with a short variable declaration

It’s possible to declare multiple variables atthe same time using a short variable declaration. They must all be on the same line, and each variable must have a corresponding initial value. The notation looks like<var1>, <var2>, …, <varN> := <val1>, <val2>, …, <valN>. The variable names are on the left-hand side of:=, separated by,. The initial values are on the right-hand side of:= again, each separated by,. The leftmost variable name gets the leftmost value. There must be an equal number of namesand values.

Here is an example that uses our previousexercise’s code:

package mainimport (  "fmt"  "time")func main() {  Debug, LogLevel, startUpTime := false, "info", time.Now()  fmt.Println(Debug, LogLevel, startUpTime)}

The following isthe output:

Figure 1.9: Example output displaying the variable values for the program with a variable declaring function

Figure 1.9: Example output displaying the variable values for the program with a variable declaring function

Sometimes, you do see real-world code like this. It’s a little hard to read, so it’s not common to see it in terms of literal values. This doesn’t mean this isn’t common, though – it’s very common when calling functions that return multiple values. We’ll cover this in detail when welook at functions later inthis book.

Exercise 1.06 – declaring multiple variables from a function

In this exercise, we’ll call a function that returns multiple values, and we’ll assign each value to a new variable. Then, we’ll print the values to the console. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import (  "fmt"  "time")
  4. Create a function that returnsthree values:
    func getConfig() (bool, string, time.Time) {
  5. In the function, return three literal values, each separatedby,:
      return false, "info", time.Now()
  6. Closethe function:
    }
  7. Create themain() function:
    func main() {
  8. Using a short variable declaration, capture the values that were returned from the function’s threenew variables:
      Debug, LogLevel, startUpTime := getConfig()
  9. Print the three variables tothe console:
      fmt.Println(Debug, LogLevel, startUpTime)
  10. Close themain() function:
    }
  11. Save the file. Then, in the new folder, runthe following:
    go run .

    The following isthe output:

Figure 1.10: Output displaying the variable values for the program with the variable declaring function

Figure 1.10: Output displaying the variable values for the program with the variable declaring function

In this exercise, we were able to call a function that returned multiple values and capture them using a short variable declaration in one line. If we used thevar notation, it would looklike this:

var (  Debug bool  LogLevel string  startUpTime time.Time)Debug, LogLevel, startUpTime = getConfig()

Short variable notation is a big part of how Go has the feel of adynamic language.

We’re not quite done withvar yet, though – it still has a useful trick upits sleeve.

Using var to declare multiple variables in one line

While it’s more common to use a short variable declaration, you can usevar to define multiple variables on a single line. One limitation of this is that, when declaring the type, all the values must have the same type. If you use an initial value, then each value infers its type from the literal value so that they can differ. Here’san example:

package mainimport (  "fmt"  "time")func getConfig() (bool, string, time.Time) {  return false, "info", time.Now()}func main() {  // Type only  var start, middle, end float32  fmt.Println(start, middle, end)  // Initial value mixed type  var name, left, right, top, bottom = "one", 1, 1.5, 2, 2.5  fmt.Println(name, left, right, top, bottom)  // works with functions also  var Debug, LogLevel, startUpTime = getConfig()  fmt.Println(Debug, LogLevel, startUpTime)}

The following istheoutput:

Figure 1.11: Output displaying variable values

Figure 1.11: Output displaying variable values

Most of these are more compact when using a short variable declaration. This fact means they don’t come up in real-world code much. The exception is the same type-only example. This notation can be useful when you need many variables of the same type, and you need to control thattype carefully.

Non-English variable names

Go is a UTF-8 compliant language, which means you can define variables’ names using alphabets other than the Latin alphabet that, for example, English uses. There are some limitations regarding what the name of a variable can be. The first character of the name must be a letter or_. The rest can be a mixture of letters, numbers, and_. Let’s have a look at what thislooks like:

package mainimport (  "fmt"  "time")func main() {  デバッグ := false  日志级别 := "info"  ይጀምሩ := time.Now()  _A1_Μείγμα := "" "  fmt.Println(デバッグ, 日志级别, ይጀምሩ, _A1_Μείγμα)}

The following isthe output:

Figure 1.12: Output showing variable values

Figure 1.12: Output showing variable values

Note

Languages and language: Not all programming languages allow you to use UTF-8 characters as variables and functionnames. This feature could be one of the reasons why Go has become so popular in Asian countries, particularlyin China.

Changing the value of a variable

Now that we’ve defined ourvariables, let’s see what we can do with them. First, let’s change the value from its initial value. To do that, we’ll use a similar notation to when we set an initial value. This looks like<variable> = <value>.

Exercise 1.07 – changing the value of a variable

Followthese steps:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import "fmt"
  4. Create themain() function:
    func main() {
  5. Declarea variable:
      offset := 5
  6. Print the variable tothe console:
      fmt.Println(offset)
  7. Change the value ofthe variable:
      offset = 10
  8. Print it to the console again and close themain() function:
      fmt.Println(offset)}
  9. Save the file. Then, in the new folder, runthe following:
    go run .

The following is the outputbefore changing thevariable’s value:

510

In this example, we’ve changed the value of offset from its initial value of5 to10. Anywhere you use a raw value, such as5 and10 in our example, you can use a variable. Here’s howthat looks:

package mainimport "fmt"var defaultOffset = 10func main() {  offset := defaultOffset  fmt.Println(offset)  offset = offset + defaultOffset  fmt.Println(offset)}

The following is the output after changing thevariable’s value:

1020

Next, we’ll look at how we can change multiple variables in aone-line statement.

Changing multiple values at once

In the same way that you candeclare multiple variables in one line, you can also change the value of more than one variable at a time. The syntax is similar, too; it looks like<var1>, <var2>, …, <varN> = <val1>, <val2>, …, <valN>.

Exercise 1.08 – changing multiple values at once

In this exercise, we’ll define some variables and use a one-line statement to change their values. Then, we’ll print their new values to the console. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import "fmt"
  4. Create themain() function:
    func main() {
  5. Declare our variables with aninitial value:
      query, limit, offset := "bat", 10, 0
  6. Change each variable’s values using aone-line statement:
      query, limit, offset = "ball", offset, 20
  7. Print the values to the console and close themain() function:
      fmt.Println(query, limit, offset)}
  8. Save the file. Then, in the new folder, runthe following:
    go run .

The following is the output showing the changed variable values using asingle statement:

ball 0 20

In this exercise, we were able to change multiple variables in a single line. This approach would also work when calling functions, just as it does with a variable declaration. You need to be careful with a feature like this to ensure that, first and foremost, your code is easy to read and understand. If using a one-line statement like this makes it hard to know what the code is doing, then it’s better to take up more lines to writethe code.

Next, we’ll look at what operators are and how they can beused to change your variables ininteresting ways.

Operators

While variables hold the data for your application, they become truly useful when you start using them to build the logic of yoursoftware. Operators are the tools you use to work with your software’s data. With operators, you can compare data to other data – for example, you can check whether a price is too low or too high in a trading application. You can also use operators to manipulate data. For example, you can use operators to add the costs of all the items in a shopping cart to get thetotal price.

The following list mentions groupsof operators:

  • Arithmetic operators: These are used for math-related tasks such as addition, subtraction,and multiplication.
  • Comparison operators: These areused to compare two values; for example, whether they are equal, not equal, less than, or greater thaneach other.
  • Logical operators: These are used with Boolean values to see whether they are both true, only one is true, or whether abool valueis false.
  • Address operators: We’ll coverthese in detail soon when we look at pointers. These are used to workwith them.
  • Receive operators: These are usedwhen working with Go channels. We’ll cover this later inthis book.

Exercise 1.09 – using operators with numbers

In this exercise, we are going to simulate a restaurant bill. To build our simulation, we’ll need to use mathematic and comparison operators. We’ll start by exploring all the major usesfor operators.

In our simulation, we’ll sum everything together and work out the tip based on a percentage. Then, we’ll use a comparison operator to see whether the customer gets a reward. Let’sget started:

Note

We have considered the US dollar as the currency for this exercise. You may consider any currency of your choice; the main focus here isthe operations.

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packagesyou’ll need:
    import "fmt"
  4. Create themain() function:
    func main() {
  5. Create a variable to hold the total. For this item on the bill, the customer purchased two items that cost 13 USD. We must use*to do the multiplication. Then, we must printa subtotal:
      // Main course  var total float64 = 2 * 13  fmt.Println("Sub :", total)
  6. Here, they purchased four items that cost 2.25 USD. We must use multiplication to get the total of these items, use+ to add it to the previous total value, and then assign that back tothe total:
      // Drinks  total = total + (4 * 2.25)  fmt.Println("Sub :", total)
  7. This customer is getting a discountof 5 USD. Here, we use to subtract 5 USD fromthe total:
      // Discount  total = total - 5  fmt.Println("Sub :",total)
  8. Then, we use multiplication to calculate a10% tip:
      // 10% Tip  tip := total * 0.1  fmt.Println("Tip :", tip)
  9. Finally, we add the tip tothe total:
      total = total + tip  fmt.Println("Total:", total)
  10. The bill will be split between two people. Use/ to divide the total intotwo parts:
      // Split bill  split := total / 2  fmt.Println("Split:", split)
  11. Here, we’ll calculate whether the customer gets a reward. First, we’ll setvisitCount and then add 1 USD tothis visit:
      // Reward every 5th visit  visitCount := 24  visitCount = visitCount + 1
  12. Then, we’ll use% to give us any remainder after dividingvisitCount by5 USD:
      remainder := visitCount % 5
  13. The customer gets a reward on every fifth visit. If the remainder is 0, then this is one of those visits. Use the== operator to check whether the remainderis 0:
      if remainder == 0{
  14. If it is, print a message stating that they geta reward:
        fmt.Println("With this visit, you've earned a reward.")  }}
  15. Save the file. Then, in the new folder, runthe following:
    go run .

The following isthe output:

Figure 1.13: Output of operators used with numbers

Figure 1.13: Output of operators used with numbers

In this exercise, we used the math and comparison operators with numbers. They allowed us to model a complex situation – calculating a restaurant bill. There are lots of operators and which ones you can use vary with the different types of values. For example, as well as there being an addition operator for numbers, you can use the+ symbol to join strings together. Here’s thisin action:

package mainimport "fmt"func main() {  givenName := "John"  familyName := "Smith"  fullName := givenName + " " + familyName  fmt.Println("Hello,", fullName)}

The following isthe output:

Hello, John Smith

For some situations, there are some shortcuts we can make with operators. We’ll go over this in thenext section.

Bitwise operators

Go has all the familiar bitwise operators you’d find in programming languages. If you know what bitwise operators are, then there will be no surprises here for you. If you don’t know what bitwise operators are, don’t worry – they aren’t common inreal-world code.

Shorthand operators

There are a few shorthand assignmentoperators when you want to perform operations on an existing value with itsown value:

  • --: Reduce a numberby 1
  • ++: Increase a numberby 1
  • +=: Addand assign
  • -=: Subtractand assign

Exercise 1.10 – implementing shorthand operators

In this exercise, we’ll use some examplesof operator shorthand to show how they can make your code more compact and easier to write. We’ll create some variables and then use shorthand to change them, printing them out as we go. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import "fmt"
  4. Create themain() function:
    func main() {
  5. Create a variable with aninitial value:
      count := 5
  6. We’ll add to it and then assign the result back to itself. Then, we’ll printit out:
      count += 5  fmt.Println(count)
  7. Increment the value by 1 and then printit out:
      count++  fmt.Println(count)
  8. Decrement it by 1 and then printit out:
      count--  fmt.Println(count)
  9. Subtract and assign the result back to itself. Print out thenew value:
      count -= 5  fmt.Println(count)
  10. There is also a shorthand that works with strings. Definea string:
      name := "John"
  11. Next, we’ll append another string to the end of it and then printit out:
      name += " Smith"  fmt.Println("Hello,", name)
  12. Close themain() function:
    }
  13. Save the file. Then, in the newfolder, runthe following:
    go run .

The following isthe output:

Figure 1.14: Output using shorthand operators

Figure 1.14: Output using shorthand operators

In this exercise, we used some shorthand operators. One set focused on modification and then assignment. This type of operation is common, and having these shortcuts makes coding more engaging. The other operators are increment and decrement. These are useful in loops when you need to step over data one at a time. These shortcuts make it clear what you’re doing to anyone who readsyour code.

Next, we’ll look at comparing values to each otherin detail.

Comparing values

Logic in applications is a matter of having your code make a decision. These decisions are made by comparing the values of variables to the rules you define. These rules come in the form of comparisons. We use another set of operators to make these comparisons. The result ofthese comparisons is always true or false. You’ll also often need to make lots of these comparisons to make a single decision. To help with that, we havelogical operators.

These operators, for the most part, work with two values and always result in a Boolean value. You can only use logical operators withBoolean values. Let’s take a look at comparison operators and logical operators inmore detail.

Comparison operators:

  • ==: True if two values arethe same
  • !=: True if two values are notthe same
  • <: True if the left value is less than theright value
  • <=: True if the left value is less or equal to theright value
  • >: True if the left value is greater than theright value
  • >=: True if the left value is greater than or equal to theright value

Logical operators:

  • &&: True if the left and right values areboth true
  • ||: True if one or both the left and right valuesare true
  • !: This operator only works with a single value and results in true if the valueis false

Exercise 1.11 – comparing values

In this exercise, we’ll use comparison and logical operators to see what Boolean results we get when testing different conditions. We are testing to see what level of membership a user has based on the number of visitsthey’ve had.

Our membership levels areas follows:

  • Silver: Between 10 and 20visits inclusively
  • Gold: Between 21 and 30visits inclusively
  • Platinum: Over30 visits

Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import "fmt"
  4. Create themain() function:
    funcmain() {
  5. Define ourvisits variable and initialize it witha value:
      visits := 15
  6. Use the equals operator to see whether this is their first visit. Then, print the result tothe console:
      fmt.Println("First visit   :", visits == 1)
  7. Usethe not equal operator to see whether they are areturning visitor:
      fmt.Println("Return visit  :", visits != 1)
  8. Let’s check whether they are a silver member using thefollowing code:
      fmt.Println("Silver member :", visits >= 10 && visits < 21)
  9. Let’s check whether they are a gold member using thefollowing code:
      fmt.Println("Gold member   :", visits > 20 && visits <= 30)
  10. Let’s check whether they are a platinum member using thefollowing code:
      fmt.Println("Platinum member :", visits > 30)
  11. Close themain() function:
    }
  12. Save the file. Then, in the new folder, runthe following:
    go run .

The following istheoutput:

Figure 1.15: Output displaying the comparison result

Figure 1.15: Output displaying the comparison result

In this exercise, we used comparison and logical operators to make decisions about data. You can combine these operators in an unlimited number of ways to express almost any type of logic your software needsto make.

Next, we’ll look at what happens when you don’t give a variable aninitial value.

Zero values

The zero value of a variable is the empty ordefault value for that variable’s type. Go has a set of rules stating that the zero values are for all the core types. Let’s takea look:

Figure 1.16: Variable types and their zero values

Figure 1.16: Variable types and their zero values

There are other types, but they are all derived from these core types, so the same rulesstill apply.

We’ll look at the zero values of some types in theupcoming exercise.

Exercise 1.12 – zero values

In this example, we’ll define some variables without an initial value. Then, we’ll print out their values. We’re usingfmt.Printf to help us in this exercise as we can get more detail about a value’s type.fmt.Printf uses a template language that allows us to transform passed values. The substitution we’re using is%#v. This transformation is a useful tool for showing a variable’s value and type. Some other common substitutions you can try areas follows:

Figure 1.17: Table on substitutions

Figure 1.17: Table on substitutions

When usingfmt.Printf, you need to add the new line symbol yourself. You can do this by adding\n to the end of the string. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import (  "fmt"  "time")
  4. Create themain() function:
    func main() {
  5. Declare and printan integer:
      var count int  fmt.Printf("Count  : %#v \n", count)
  6. Declare and print afloat value:
      var discount float64  fmt.Printf("Discount : %#v \n", discount)
  7. Declare and print abool value:
      var debug bool  fmt.Printf("Debug  : %#v \n", debug)
  8. Declare andprint astring value:
      var message string  fmt.Printf("Message : %#v \n", message)
  9. Declare and print a collectionof strings:
      var emails []string  fmt.Printf("Emails : %#v \n", emails)
  10. Declare and print a struct (a type composed of other types; we will cover this later inthis book):
      var startTime time.Time  fmt.Printf("Start  : %#v \n", startTime)
  11. Close themain() function:
    }
  12. Save the file. Then, in the new folder, runthe following:
    go run .

The following isthe output:

Figure 1.18: Output showing initial variable values

Figure 1.18: Output showing initial variable values

In this exercise, we defined a variety of variable types without an initial value. Then, we printed them out usingfmt.Printf to expose more detail about the values. Knowing what the zero values are and how Go controls them allows you to avoid bugs and writeconcise code.

Next, we’ll look at what pointers are and how they can enable you to writeefficient software.

Value versus pointer

With values such asint,bool, andstring, when you pass them to a function, Go makes a copy of the value, and it’s the copy that’s used in the function. This copying means that a change that’s madeto the value in the function doesn’t affect the value that you used when callingthe function.

Passing values by copying tends to result in code that has fewer bugs. With this method of passing values, Go can use its simple memory management system, called the stack. The downside is thatcopying uses up more and more memory as values get passed from function to function. In real-world code, functions tend to be small, and values get passed to lots of functions, so copying by value can sometimes end up using much more memory thanis needed.

There is an alternative to copying that uses less memory. Instead of passing a value, we create something called a pointer and then pass that to functions. A pointer is not a value itself, and you can’t do anything useful with a pointer other than getting a value using it. You can think of a pointer as the address of the value you want, and to get to the value, you must go to the address. If you use a pointer, Go won’t make a copy of the value when passing a pointer toa function.

When creating a pointer to a value, Go can’t manage the value’s memory using the stack. This is because the stack relies on simple scope logic to know when it can reclaim the memory that’s used by a value, and having a pointer to a variable means these rules don’t work. Instead, Go puts the value on the heap. The heap allows the value to exist until no part of your software hasa pointer to it anymore. Go reclaims these values in what it calls its garbage collection process. This process happens periodically in the background, and you don’t need to worryabout it.

Having a pointer to a value means that a value is put on the heap, but that’s not the only reason that happens. Working out whether a value needs to be put on the heap is called escape analysis. There aretimes when a value with no pointers is put on the heap, and it’s not alwaysclear why.

You have no direct control over whether a value is put on the stack or the heap. Memory management is not part of Go’s language specification. Memory management is considered an internal implementation detail. This means it could be changed at any time, and that what we’ve spoken about are only general guidelines and not fixed rules and could change at alater date.

While the benefits of using a pointer over a value that gets passed to lots of functions are clear for memory usage, it’s not so clear for CPU usage. When a value gets copied, Go needs CPU cycles to get that memory and then release it later. Using a pointer avoids this CPU usage when passing it to a function. On the other hand, having a value on the heap means that it then needs to be managed by the complex garbage collection process. This process can become a CPU bottleneck in certain situations – for example, if there are lots of values on the heap. When this happens, the garbage collector has to do lots of checking, which uses up CPU cycles. There is no correct answer here, and the best approach is the classic performance optimization one. First, don’t prematurely optimize. When you do have a performance problem, measure before you make a change, and then measure after you’ve madea change.

Beyond performance, you can use pointers to change your code’s design. Sometimes, using pointers allows for a cleaner interface and simplifies your code. For example, if you need to know whether a value is present or not, a non-pointer value always has at least its zero value, which could be valid in your logic. You can use a pointer to allow for anis not set state as well as holding a value. This is because pointers, as well as holding the address to a value, can also benil, which means there is no value. In Go,nil is a special type that represents something not havinga value.

The ability for a pointer to be nil also means that it’s possible to get the value of a pointer when it doesn’t have a value associated with it, which means you’ll get a runtime error. To prevent runtime errors, you can compare a pointer tonil before trying to get its value. This looks like<pointer> != nil. You can compare pointers with other pointers of the same type, but they only result in true if you are comparing a pointer to itself. Nocomparison of the associated valuesgets made.

Pointers are powerful tools in the language thanks to their efficiency, ability to pass by reference (instead of pass by value) to allow functions to modify the original values, and how they allow fordynamic memory allocation using the garbage collector. However, with any great tool comes great responsibility. Pointers can be dangerous if misused, such as in the event memory is freed (deallocated) and the pointer becomes a “dangling pointer,” which could lead to undefined behavior if accessed. There is also the potential for memory leaks, unsafe operations due to direct memory access, and concurrency challenges if there are shared pointers that could introduce data races. Overall, Go’s pointers are generally straightforward and less error-prone compared to other languages suchas C.

Getting a pointer

To get a pointer, you have a few options. You can declare a variable as being a pointer type using avar statement. You can do this by adding* at the front of most types. This notation looks likevar <name> *<type>. The initial value of a variable that uses this method isnil. You can use the built-innew function for this. This function is intended to be used to get some memory for a type and return a pointer to that address. The notation looks like<name> := new(<type>). Thenew function can be used withvar too. You can also get a pointer from an existing variable using&, which you can read as "address of". This looks like<var1> := &<var2>.

Exercise 1.13 – getting a pointer

In this exercise, we’ll use each of the methods we can use to get a pointer variable. Then, we’ll print them to theconsole usingfmt.Printf to see what their types and value are. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import (  "fmt"  "time")
  4. Create themain() function:
    func main() {
  5. Declare apointer using avar statement:
      var count1 *int
  6. Create a variableusingnew:
      count2 := new(int)
  7. You can’t take the address of a literal number. Create a temporary variable to holda number:
      countTemp := 5
  8. Using&, create a pointer from theexisting variable:
      count3 := &countTemp
  9. It’s possible to create a pointer from some types without a temporary variable. Here, we’re using our trustytime struct:
      t := &time.Time{}
  10. Print eachoutusingfmt.Printf:
      fmt.Printf("count1: %#v\n", count1)  fmt.Printf("count2: %#v\n", count2)  fmt.Printf("count3: %#v\n", count3)  fmt.Printf("time : %#v\n", t)
  11. Close themain() function:
    }
  12. Save the file. Then, in the new folder, runthe following:
    go run .

The following isthe output:

Figure 1.19: Output showing pointers

Figure 1.19: Output showing pointers

In this exercise, we looked at three different ways of creating a pointer. Each one is useful, depending on what your code needs. With thevar statement, the pointer has a value ofnil, while the others already have a value address associated with them. For thetime variable, we can see the value, but we can tell it’s a pointer because its output startswith&.

Next, we’ll see how we can get a value froma pointer.

Getting a value from a pointer

In the previous exercise, when we printed out the pointer variables for theint pointers to the console, weeither gotnil or saw a memory address. To get to the value a pointer is associated with, you must dereference the value using* in front of the variable name. This lookslikefmt.Println(*<val>).

Dereferencing a zero ornil pointer is a common bug in Go software as the compiler can’t warn you about it, and it happens when the app is running. Therefore, it’s always best practice to check that a pointer is notnil before dereferencing it unless you are certain it’snotnil.

You don’t always need to dereference – for example, when a property or function is on a struct. Don’t worry too much about when you shouldn’t be dereferencing as Go gives you clear errors regarding when you can and can’t dereferencea value.

Exercise 1.14 – getting a value from a pointer

In this exercise, we’ll update our previous exercise to dereference the values from the pointers. We’ll also addnil checks to prevent us from getting any errors. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import (  "fmt"  "time")
  4. Create themain() function:
    func main() {
  5. Our pointers are declared in the same way as theywere previously:
      var count1 *int  count2 := new(int)  countTemp := 5  count3 := &countTemp  t := &time.Time{}
  6. For counts1, 2, and 3, weneed to add anil check and add* in front of thevariable name:
      if count1 != nil {    fmt.Printf("count1: %#v\n", *count1)  }  if count2 != nil {    fmt.Printf("count2: %#v\n", *count2)  }  if count3 != nil {    fmt.Printf("count3: %#v\n", *count3)  }
  7. We’ll also add anil check for ourtime variable:
      if t != nil {
  8. We’ll dereference the variable using*, just like we did with thecount variables:
        fmt.Printf("time : %#v\n", *t)
  9. Here, we’re calling a function on ourtime variable. This time, we don’t need todereference it:
        fmt.Printf("time : %#v\n", t.String())
  10. Close thenil check:
      }
  11. Close themain() function:
    }
  12. Save the file. Then, in the new folder, runthe following:
    go run .

The following istheoutput:

Figure 1.20: Output showing getting values from pointers

Figure 1.20: Output showing getting values from pointers

In this exercise, we used dereferencing to get the values from our pointers. We also usednil checks to prevent dereferencing errors. From the output of this exercise, we can see thatcount1 was anil value and that we’d have gotten an error if we tried to dereference.count2 was created usingnew, and its value is a zero value for its type.count3 also had a value that matched the value of the variable we got the pointer from. With ourtime variable, we were able to dereference the whole struct, which is why our output doesn’t startwith&.

Next, we’ll look at how using a pointer allows us to change the design ofour code.

Function design with pointers

We’ll cover functions in moredetail later in this book, but you know enough from what we’ve done so far to see how using a pointer can change how you use a function. A function must be coded to accept pointers, and it’s not something that you can choose whether to do or not. If you have a pointer variable or have passed a pointer of a variable to a function, any changes that are made to the value of the variable in the function also affect the value of the variable outside ofthe function.

Exercise 1.15 – function design with pointers

In this exercise, we’ll create two functions: one that accepts a number by value, adds 5 to it, and then prints the number to the console; and another function that accepts a number as a pointer, adds 5 to it, and then prints the number out. We’ll also print the number out after calling eachfunction to assess what effect it has on the variable that was passed to the function. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import "fmt"
  4. Create a function that takes anint pointer asan argument:
    func add5Value(count int){
  5. Add5 to thepassed number:
      count += 5
  6. Print the updated number tothe console:
      fmt.Println("add5Value   :", count)
  7. Closethe function:
    }
  8. Create another function that takesanint pointer:
    func add5Point(count *int) {
  9. Dereference the value andadd5to it:
      *count += 5
  10. Print out the updated value ofcount anddereference it:
      fmt.Println("add5Point   :", *count)
  11. Closethe function:
    }
  12. Create themain() function:
    func main() {
  13. Declare anint variable:
      var count int
  14. Call the first function withthe variable:
      add5Value(count)
  15. Print the current value ofthe variable:
      fmt.Println("add5Value post:", count)
  16. Call thesecondfunction. This time, you’ll need to use& to pass a pointer tothe variable:
      add5Point(&count)
  17. Print the current value ofthe variable:
      fmt.Println("add5Point post:", count)
  18. Close themain() function:
    }
  19. Save the file. Then, in the new folder, runthe following:
    go run .

The following isthe output:

Figure 1.21: Output displaying the current value of the variable

Figure 1.21: Output displaying the current value of the variable

In this exercise, we showed you how passing values by a pointer can affect the value variables that are passed to them. We saw that, when passing by value, the changes you make to the value in a function do not affect the value of the variable that’s passed to the function, while passing a pointer to a value does change the value of the variable passed tothe function.

You can use this fact to overcome awkward design problems and sometimes simplify the design of your code. Passingvalues by a pointer has traditionally been shown to be more error-prone, so use this design sparingly. It’s also common to use pointers in functions to create more efficient code, which Go’s standard library doesa lot.

Activity 1.02 – pointer value swap

In this activity, your job is tofinish some code a co-worker started. Here, we have some unfinished code for you to complete. Your task is to fill in the missing code, where the comments are to swap the values ofa andb. Theswap function only accepts pointers and doesn’treturn anything:

package mainimport "fmt"func main() {  a, b := 5, 10  // call swap here  fmt.Println(a == 10, b == 5)}func swap(a *int, b *int) {  // swap the values here}

Followthese steps:

  1. Call theswap function, ensuring you are passinga pointer.
  2. In theswap function, assign the values to the other pointer, ensuring you dereferencethe values.

The following is theexpectedoutput:

true true

Next, we’ll look at how we can create variables with afixed value.

Constants

Constants are like variables, but you can’t change their initial values. These are useful for situations where the value of a constant doesn’t need to or shouldn’t change when your code is running. You could make the argument that you could hardcode those values into the code and it would have a similar effect. Experience has shown us that while these values don’t need to change at runtime, they may need to change later. If that happens, it can be an arduous and error-prone task to track down and fix all the hardcoded values. Using a constant is a tiny amount of work now that can save you a great deal ofeffort later.

Constant declarations are similar tovar statements. With a constant, the initial value is required. Types are optional and inferred if left out. The initial value can be a literal or a simple statement and can use the values of other constants. Likevar, you can declare multiple constants in one statement. Here arethe notations:

constant <name> <type> = <value>constant (  <name1> <type1> = <value1>  <name2> <type2> = <value3>…  <nameN> <typeN> = <valueN>)

Exercise 1.16 – constants

In this exercise, we have a performance problem: our database server is too slow. We are going to create a custom memory cache. We’ll use Go’smap collection type, which will act as the cache. There is a global limit on the number of items that can be in the cache. We’ll use onemap to help keep track of the number of items in the cache. We have two types of data we need to cache: books and CDs. Both use the ID, so we need a way to separate the two types of items in the shared cache. We need a way to set and get items fromthe cache.

We’re going to set the maximum number of items in the cache. We’ll also use constants to add a prefix to differentiate between books and CDs. Let’sget started:

  1. Create a new folder and add amain.go fileto it.
  2. Inmain.go, add themain package name to the top ofthe file:
    package main
  3. Import the packageswe’ll need:
    import "fmt"
  4. Create a constant that’s our globallimit size:
    constGlobalLimit = 100
  5. Create aMaxCacheSize constant that is 10 times the globallimit size:
    const MaxCacheSize int = 10 * GlobalLimit
  6. Create ourcache prefixes:
    const (  CacheKeyBook = "book_"  CacheKeyCD = "cd_")
  7. Declare amap value that has astring value for a key and astring value for its valuesasour cache:
    var cache map[string]string
  8. Create a function to get items fromthe cache:
    func cacheGet(key string) string {  return cache[key]}
  9. Create a function that sets items inthe cache:
    func cacheSet(key, val string) {
  10. In this function, check out theMaxCacheSize constant to stop the cache going overthat size:
      if len(cache)+1 >= MaxCacheSize {    return  }  cache[key] = val}
  11. Create a function to get a book fromthe cache:
    func GetBook(isbn string) string {
  12. Use the book cache prefix to create aunique key:
      return cacheGet(CacheKeyBook + isbn)}
  13. Create a function to add a book tothe cache:
    func SetBook(isbn string, name string) {
  14. Use the book cache prefix to create aunique key:
      cacheSet(CacheKeyBook+isbn, name)}
  15. Create a function to get CD data fromthe cache:
    func GetCD(sku string) string {
  16. Use theCD cache prefix to create aunique key:
      return cacheGet(CacheKeyCD + sku)}
  17. Create a function to add CDs to theshared cache:
    func SetCD(sku string, title string) {
  18. Use theCD cache prefix constant to build a unique key for theshared cache:
      cacheSet(CacheKeyCD+sku, title)}
  19. Create themain() function:
    func main() {
  20. Initialize our cache by creating amap value:
      cache = make(map[string]string)
  21. Add a book tothe cache:
      SetBook("1234-5678", "Get Ready To Go")
  22. Add aCD cache prefix tothe cache:
      SetCD("1234-5678", "Get Ready To Go Audio Book")
  23. Get and print thatBook fromthe cache:
      fmt.Println("Book :", GetBook("1234-5678"))
  24. Get and print thatCD fromthe cache:
      fmt.Println("CD :", GetCD("1234-5678"))
  25. Close themain() function:
    }
  26. Save the file. Then, in the new folder, runthe following:
    go run .

The following isthe output:

Figure 1.22: Output displaying the Book and CD caches

Figure 1.22: Output displaying the Book and CD caches

In this exercise, we usedconstants to define values that don’t need to change while the code is running. We declared then using a variety of notation options, some with the typeset and some without. We declared a single constant and multiple constants in asingle statement.

Next, we’ll look at a variation of constants for values that are moreclosely related.

Enums

Enums are a way ofdefining a fixed list of values that are all related. Go doesn’t have a built-in type for enums, but it does provide tools such asiota to let you define your own using constants. We’ll explorethis now.

For example, in the following code, we have the days of the week defined as constants. This code is a good candidate for Go’siota feature:

…const (  Sunday  = 0  Monday  = 1  Tuesday = 2  Wednesday = 3  Thursday = 4  Friday  = 5  Saturday = 6)…

Withiota, Go helps us manage lists just like this. Usingiota, the following code is equal to thepreceding code:

…const (  Sunday = iota  Monday  Tuesday  Wednesday  Thursday  Friday  Saturday)…

Now, we haveiota assigning the numbers for us. Usingiota makes enums easier to create and maintain, especially if you need to add a new value to the middle of the code later. Order matters when usingiota as it is an identifier that tells the Go compiler to start the first value at 0 and increment by 1 for each subsequent value in the case of this example. Withiota, you can skip values using_, start with a different offset, and even use morecomplicated calculations.

Next, we’lltake a detailed lookat Go’s variable scoping rules and how they affect how youwrite code.

Scope

All the variables in Go live ina scope. The top-level scope is the package scope. A scope can have child scopes within it. There are a few ways a child scope gets defined; the easiest way to think about this is that when you see{, you are starting a new child scope, and that child scope ends when you get to a matching}. The parent-child relationship is defined when the code compiles, not when the code runs. When accessing a variable, Go looks at the scope the code was defined in. If it can’t find a variable with that name, it looks in the parent scope, then the grandparent scope, all the way until it gets to the package scope. It stops looking once it finds a variable with a matching name or raises an error if it can’t finda match.

To put it another way, when your code uses a variable, Go needs to work out where that variable was defined. It starts its search in the scope of the code using the variable it’s currently running in. If a variable definition using that name is in that scope, then it stops looking and uses the variable definition to complete its work. If it can’t find a variable definition, then it starts walking up the stack of scopes, stopping as soon as it finds a variable with that name. This searching is all done based on a variable name. If a variable with that name is found but is of the wrong type, Go raisesan error.

In this example, we have four different scopes, but we define thelevel variable once. This means that no matter where you uselevel, the same variableis used:

package mainimport "fmt"var level = "pkg"func main() {  fmt.Println("Main start :", level)  if true {    fmt.Println("Block start :", level)    funcA()  }}func funcA() {  fmt.Println("funcA start :", level)}

The following is the output displaying variables whenusinglevel:

Main start : pkgBlock start : pkgfuncA start : pkg

In this example, we’ve shadowed thelevel variable. This newlevel variable is not related to thelevel variable in the package scope. When we printlevel in the block, the Go runtime stops looking for variables calledlevel as soon as it finds the one defined inmain. This logic results in a different value getting printed out once that new variable shadows the package variable. You can also see that it’s a different variable because it’s a different type, and a variable can’t have its type changedin Go:

package mainimport "fmt"var level = "pkg"func main() {  fmt.Println("Main start :", level)  // Create a shadow variable  level := 42  if true{    fmt.Println("Block start :", level)    funcA()  }  fmt.Println("Main end :", level)}func funcA() {  fmt.Println("funcA start :", level)}

The following isthe output:

Main start : pkgBlock start : 42funcA start : pkgMain end : 42

Go’s static scope resolution comes into play when we callfuncA. That’s why, whenfuncA runs, it still sees the package scope’slevel variable. The scope resolution doesn’tpay attention to wherefuncAgets called.

You can’t access variables defined in achild scope:

package mainimport "fmt"func main() {  {    level := "Nest 1"    fmt.Println("Block end :", level)  }  // Error: undefined: level  //fmt.Println("Main end  :", level)}

The following isthe output:

Figure 1.23: Output displaying an error

Figure 1.23: Output displaying an error

Activity 1.03 – message bug

The following code doesn’twork. The person who wrote it can’t fix it, and they’ve asked you to help them. Can you get itto work?

package mainimport "fmt"func main() {  count := 5  if count > 5 {    message := "Greater than 5"  } else {    message := "Not greater than 5"  }  fmt.Println(message)}

Followthese steps:

  1. Run the code and see what theoutput is.
  2. The problem is withmessage; make a change tothe code.
  3. Rerun the code and see what differenceit makes.
  4. Repeat this process until you see theexpected output.

    The following is theexpected output:

    Not greater than 5

In this activity, we saw that where you define your variables has a big impact on the code. Always think about the scope you need your variables to be in whendefining them.

In the next activity, we are going to look at a similar problem that is abit trickier.

Activity 1.04 – bad count bug

Your friend is back, and they haveanother bug in their code. This code should printtrue, but it’s printingfalse. Can you help them fixthe bug?

package mainimport "fmt"func main() {  count := 0  if count < 5 {    count := 10    count++  }  fmt.Println(count == 11)}

Followthese steps:

  1. Run the code and see what theoutput is.
  2. The problem is withcount; make a change tothe code.
  3. Rerun the code and see what differenceit makes.
  4. Repeat this processuntil you see theexpected output.

The following is theexpected output:

True

Summary

In this chapter, we got into the nitty-gritty of variables, including how variables are declared, and all the different notations you can use to declare them. This variety of notation gives you a nice compact notation to use for 90% of your work, while still giving you the power to be very specific when you need to the other 10% of the time. We looked at how to change and update the value of variables after you’ve declared them. Again, Go gives you some great shorthand to help in the most common use cases to make your life easier. All your data ends up in some form of variable. Data is what makes code dynamic and responsive. Without data, your code could only ever do exactly one thing; data unleashes the true powerof software.

Now that your application has data, it needs to make choices based on that data. That’s where variable comparison comes in. This helps us see whether something is true or false, bigger or smaller, and so on, and it also helps us make choices based on the results ofthose comparisons.

We explored how Go decided to implement its variable system by looking at zero values, pointers, and scope logic. At this point, we know that these are the details that can be the difference between delivering bug-free efficient software and notdoing so.

We also took a look at how we can declare immutable variables by using constants and howiota can help manage lists or related constants to work, suchas enums.

In the next chapter, we’ll start to put our variables to work by defining logic and looping over collectionsof variables.

Left arrow icon

Page1 of 11

Right arrow icon
Download code iconDownload Code

Key benefits

  • Leverage Go's standard library through practical examples and simplify development tasks using best practices
  • Master effective idiomatic Go syntax, including variables, functions, and loops, to handle data
  • Build fully functional web applications with capabilities such as database connectivity and RESTful API creation
  • Purchase of the print or Kindle book includes a free PDF eBook

Description

Go Programming – From Beginner to Professional is a comprehensive guide that takes your proficiency in the Go programming language from novice to expert. Starting with fundamental concepts, this book covers variables, command-line tools, and working with data before delving into advanced concepts, including error handling, interfaces, and generics, harnessing Go’s latest features through hands-on exercises. Along the way, you’ll learn to structure projects using Go modules, manage packages effectively, and master debugging techniques.As you progress, you’ll get to grips with practical application-centric aspects such as command-line programming, file manipulation, and working with SQL databases. Additionally, the book explores web server development, RESTful APIs, and utilizing the Go HTTP client to interact with web applications. Further enhancing your Go skills, you’ll learn concurrent programming, testing methodologies, Go tools, and how to deploy applications in the cloud. Throughout the book, you’ll uncover Go’s hidden gems and gain insights into time manipulation, best practices, and more.By the end of this book, you’ll have worked through practical exercises and activities that’ll equip you with the knowledge and skills needed to excel as a proficient Go developer, primed for success in real-world projects.

Who is this book for?

Designed for both complete beginners in Go as well as professionals transitioning from another programming language, this book equips developers with skills needed to build real-world projects and launch their career in Go. With a step-by-step approach, beginners can grasp Go fundamentals even without prior programming experience, and gradually advance to idiomatic Go best practices, exploring the latest features of the language.

What you will learn

  • Understand the Go syntax and apply it proficiently to handle data and write functions
  • Debug your Go code to troubleshoot development problems
  • Safely handle errors and recover from panics
  • Implement polymorphism using interfaces and gain insight into generics
  • Work with files and connect to popular external databases
  • Create an HTTP client and server and work with a RESTful web API
  • Use concurrency to design efficient software
  • Use Go tools to simplify development and improve your code

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date :Mar 29, 2024
Length:680 pages
Edition :2nd
Language :English
ISBN-13 :9781803246307
Category :
Languages :

What do you get with eBook?

Product feature iconInstant access to your Digital eBook purchase
Product feature icon Download this book inEPUB andPDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature iconDRM FREE - Read whenever, wherever and however you want
Product feature iconAI Assistant (beta) to help accelerate your learning
OR

Contact Details

Modal Close icon
Payment Processing...
tickCompleted

Billing Address

Product Details

Publication date :Mar 29, 2024
Length:680 pages
Edition :2nd
Language :English
ISBN-13 :9781803246307
Category :
Languages :
Concepts :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99billed monthly
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconSimple pricing, no contract
$199.99billed annually
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconChoose a DRM-free eBook or Video every month to keep
Feature tick iconPLUS own as many other DRM-free eBooks or Videos as you like for just Mex$85 each
Feature tick iconExclusive print discounts
$279.99billed in 18 months
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconChoose a DRM-free eBook or Video every month to keep
Feature tick iconPLUS own as many other DRM-free eBooks or Videos as you like for just Mex$85 each
Feature tick iconExclusive print discounts

Frequently bought together


Solutions Architect's Handbook
Solutions Architect's Handbook
Read more
Mar 2024582 pages
Full star icon4.7 (60)
eBook
eBook
Mex$885.99Mex$984.99
Mex$1230.99
Mastering Go
Mastering Go
Read more
Mar 2024740 pages
Full star icon4.8 (27)
eBook
eBook
Mex$811.99Mex$902.99
Mex$1128.99
Go Programming - From Beginner to Professional
Go Programming - From Beginner to Professional
Read more
Mar 2024680 pages
Full star icon4.8 (11)
eBook
eBook
Mex$664.99Mex$738.99
Mex$922.99
Stars icon
TotalMex$3,282.97
Solutions Architect's Handbook
Mex$1230.99
Mastering Go
Mex$1128.99
Go Programming - From Beginner to Professional
Mex$922.99
TotalMex$3,282.97Stars icon

Table of Contents

29 Chapters
Part 1: ScriptsChevron down iconChevron up icon
Part 1: Scripts
Chapter 1: Variables and OperatorsChevron down iconChevron up icon
Chapter 1: Variables and Operators
Technical requirements
Introduction to Go
What does Go look like?
Declaring variables
Changing the value of a variable
Operators
Value versus pointer
Constants
Enums
Summary
Chapter 2: Command and ControlChevron down iconChevron up icon
Chapter 2: Command and Control
Technical requirements
Introduction
if statements
Expression switch statements
Loops
break and continue
goto statements
Summary
Chapter 3: Core TypesChevron down iconChevron up icon
Chapter 3: Core Types
Technical requirements
Introduction
True and false
Numbers
byte
Text
The nil value
Summary
Chapter 4: Complex TypesChevron down iconChevron up icon
Chapter 4: Complex Types
Technical requirements
Introduction
Collection types
Arrays
Slices
Simple custom types
Structs
Summary
Part 2: ComponentsChevron down iconChevron up icon
Part 2: Components
Chapter 5: Functions – Reduce, Reuse, and RecycleChevron down iconChevron up icon
Chapter 5: Functions – Reduce, Reuse, and Recycle
Technical requirements
Introduction
Functions
The checkNumbers function
Parameters
Naked returns
Closures
defer
Separating similar code
Summary
Chapter 6: Don’t Panic! Handle Your ErrorsChevron down iconChevron up icon
Chapter 6: Don’t Panic! Handle Your Errors
Technical requirements
Introduction
What are errors?
Error interface type
Panic
Recover
Summary
Chapter 7: InterfacesChevron down iconChevron up icon
Chapter 7: Interfaces
Technical requirements
Introduction
Interface
Duck typing
Polymorphism
Summary
Chapter 8: Generic Algorithm SuperpowersChevron down iconChevron up icon
Chapter 8: Generic Algorithm Superpowers
Technical requirements
Introduction
When to use generics?
Type parameters
Type constraints
Type inference
When to use generics versus interfaces
What are some best practices?
Summary
Part 3: ModulesChevron down iconChevron up icon
Part 3: Modules
Chapter 9: Using Go Modules to Define a ProjectChevron down iconChevron up icon
Chapter 9: Using Go Modules to Define a Project
Technical requirements
Introduction
What is a module?
How are modules helpful?
Exercise 09.01 – creating and using your first module
When should you use external modules, and why?
Exercise 09.02 – using an external module within our module
Consuming multiple modules within a project
Defining multiple modules within a project
Go workspaces
Summary
Chapter 10: Packages Keep Projects ManageableChevron down iconChevron up icon
Chapter 10: Packages Keep Projects Manageable
Technical requirements
Introduction
What is a package?
Exported and unexported code
The init() function
Summary
Chapter 11: Bug-Busting Debugging SkillsChevron down iconChevron up icon
Chapter 11: Bug-Busting Debugging Skills
Technical requirements
Introduction
Methods for bug-free code
Basic debugging
Logging
Logging fatal errors
Debugging in live or restricted environments
Summary
Chapter 12: About TimeChevron down iconChevron up icon
Chapter 12: About Time
Technical requirements
Introduction
Making time
Comparing time
Duration calculation
Managing time
Formatting time
Summary
Part 4: ApplicationsChevron down iconChevron up icon
Part 4: Applications
Chapter 13: Programming from the Command LineChevron down iconChevron up icon
Chapter 13: Programming from the Command Line
Technical requirements
Introduction
Reading arguments
Using flags to control behavior
Streaming large amounts of data in and out of your application
Exit codes and command line best practices
Knowing when to stop by watching for interrupts
Starting other commands from your application
Terminal UIs
go install
Summary
Chapter 14: File and SystemsChevron down iconChevron up icon
Chapter 14: File and Systems
Technical requirements
Introduction
Filesystem
Flags and arguments
Create and write to files
CSV
Embedding
Summary
Chapter 15: SQL and DatabasesChevron down iconChevron up icon
Chapter 15: SQL and Databases
Technical requirements
Introduction
Understanding the database
Database API and drivers
Connecting to databases
Creating tables
Inserting data
Retrieving data
Updating existing data
Deleting data
Truncating and deleting table
Adding users with GORM
Summary
Part 5: Building For The WebChevron down iconChevron up icon
Part 5: Building For The Web
Chapter 16: Web ServersChevron down iconChevron up icon
Chapter 16: Web Servers
Technical requirements
Introduction
How to build a basic server
HTTP handler
Simple routing
Handler versus handler function
Adding middleware
Dynamic content
Templating
Static resources
Getting some style
Getting dynamic
Embedding external files
Summary
Chapter 17: Using the Go HTTP ClientChevron down iconChevron up icon
Chapter 17: Using the Go HTTP Client
Technical requirements
Introduction
The Go HTTP Client and its uses
Sending a request to a server
Structured data
Sending data to a server
Summary
Part 6: ProfessionalChevron down iconChevron up icon
Part 6: Professional
Chapter 18: Concurrent WorkChevron down iconChevron up icon
Chapter 18: Concurrent Work
Technical requirements
Introduction
Goroutines
WaitGroup
Race conditions
Atomic operations
Invisible concurrency
Channels
The importance of concurrency
Concurrency patterns
Buffers
HTTP servers
Methods as Goroutines
Go context package
Concurrent work with sync.Cond
The thread-safe map
Summary
Chapter 19: TestingChevron down iconChevron up icon
Chapter 19: Testing
Technical requirements
Introduction
Unit tests
Integration tests
E2E tests
HTTP testing
Fuzz testing
Benchmarks
Test suites
Test report
Code coverage
Summary
Chapter 20: Using Go ToolsChevron down iconChevron up icon
Chapter 20: Using Go Tools
Technical requirements
Introduction
The go build tool
The go run tool
The gofmt tool
The goimports tool
The go vet tool
The Go race detector
The go doc tool
The go get tool
Summary
Chapter 21: Go in the CloudChevron down iconChevron up icon
Chapter 21: Go in the Cloud
Technical requirements
Introduction
Making your app monitorable by systems such as Prometheus
Enabling deep insights through OpenTelemetry
Best practices for putting your Go application in a container
Making your app ready to work with orchestrators such as Kubernetes
Summary
IndexChevron down iconChevron up icon
Index
Why subscribe?
Other Books You May EnjoyChevron down iconChevron up icon
Other Books You May Enjoy
Packt is searching for authors like you
Share Your Thoughts
Download a free PDF copy of this book

Recommendations for you

Left arrow icon
Debunking C++ Myths
Debunking C++ Myths
Read more
Dec 2024226 pages
Full star icon5 (1)
eBook
eBook
Mex$590.99Mex$656.99
Mex$820.99
Go Recipes for Developers
Go Recipes for Developers
Read more
Dec 2024350 pages
eBook
eBook
Mex$590.99Mex$656.99
Mex$820.99
50 Algorithms Every Programmer Should Know
50 Algorithms Every Programmer Should Know
Read more
Sep 2023538 pages
Full star icon4.5 (68)
eBook
eBook
Mex$737.99Mex$820.99
Mex$1025.99
Mex$1025.99
Asynchronous Programming with C++
Asynchronous Programming with C++
Read more
Nov 2024424 pages
Full star icon5 (1)
eBook
eBook
Mex$620.98Mex$689.99
Mex$861.99
Modern CMake for C++
Modern CMake for C++
Read more
May 2024504 pages
Full star icon4.7 (12)
eBook
eBook
Mex$737.99Mex$820.99
Mex$1025.99
Learn Python Programming
Learn Python Programming
Read more
Nov 2024616 pages
Full star icon5 (1)
eBook
eBook
Mex$590.99Mex$656.99
Mex$820.99
Learn to Code with Rust
Learn to Code with Rust
Read more
Nov 202457hrs 40mins
Video
Video
Mex$1538.99
Modern Python Cookbook
Modern Python Cookbook
Read more
Jul 2024818 pages
Full star icon4.9 (21)
eBook
eBook
Mex$811.99Mex$902.99
Mex$1128.99
Right arrow icon

Customer reviews

Top Reviews
Rating distribution
Full star iconFull star iconFull star iconFull star iconHalf star icon4.8
(11 Ratings)
5 star90.9%
4 star0%
3 star9.1%
2 star0%
1 star0%
Filter icon Filter
Top Reviews

Filter reviews by




GustavoMay 31, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
Exciting started
Subscriber reviewPackt
AndresApr 19, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
Great content!! Easy to undrstand for a junior developer.
Subscriber reviewPackt
Amazon CustomerMay 16, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
Go Programming - Beginner to Professional" by Samantha Coyle is an outstanding resource for mastering Go programming. Here’s why:1.Starts with the basics and progresses to advanced topics, ensuring a solid foundation and smooth transition.2.Includes hands-on exercises and projects at the end of each chapter to reinforce learning.3. Author's clear explanations and engaging style make complex topics accessible and enjoyable to read.Pros:Well-structured for all levelsClear, practical examplesEffective hands-on exercisesAccessible writing styleConclusion: Whether you're new to programming or experienced in other languages, this book is an excellent guide to becoming proficient in Go. Highly recommended!
Amazon Verified reviewAmazon
TinyMay 09, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
Need to learn Go? Need to upskill your Go-fu capabilities? And of course, we are talking about the Go programming language and not the antique game from China. This is a comprehensive book covering all aspects of GO programming. Highlights some of the challenges, suggests tips and tricks, and offers sample. Recommend as a reference for anyone working on Go applications, or just in need of a tuneup. This will seem like a long book (600+ pages) but much of that space is taken up by the extensive coding samples.
Amazon Verified reviewAmazon
MARIAN MONTAGNINOMay 17, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
I'm so impressed with this book—it's incredibly comprehensive, taking you from beginner to professional. It starts with the basics and progresses to creating HTTP services and command line interfaces, two very common uses of Golang. The numerous examples reinforce your understanding of each topic, making the learning curve much easier to manage. This book stands out not only because it uses the latest version of Golang, but also because Samantha has broken down each topic in a way that's easy to digest. If you're looking for one book to learn Golang, I highly recommend this one!
Amazon Verified reviewAmazon
  • Arrow left icon Previous
  • 1
  • 2
  • 3
  • Arrow right icon Next

People who bought this also bought

Left arrow icon
50 Algorithms Every Programmer Should Know
50 Algorithms Every Programmer Should Know
Read more
Sep 2023538 pages
Full star icon4.5 (68)
eBook
eBook
Mex$737.99Mex$820.99
Mex$1025.99
Mex$1025.99
Event-Driven Architecture in Golang
Event-Driven Architecture in Golang
Read more
Nov 2022384 pages
Full star icon4.9 (11)
eBook
eBook
Mex$737.99Mex$820.99
Mex$1025.99
The Python Workshop Second Edition
The Python Workshop Second Edition
Read more
Nov 2022600 pages
Full star icon4.6 (22)
eBook
eBook
Mex$767.99Mex$853.99
Mex$1066.99
Template Metaprogramming with C++
Template Metaprogramming with C++
Read more
Aug 2022480 pages
Full star icon4.6 (14)
eBook
eBook
Mex$693.99Mex$771.99
Mex$963.99
Domain-Driven Design with Golang
Domain-Driven Design with Golang
Read more
Dec 2022204 pages
Full star icon4.4 (19)
eBook
eBook
Mex$664.99Mex$738.99
Mex$922.99
Right arrow icon

About the author

Profile icon Samantha Coyle
Samantha Coyle
LinkedIn iconGithub icon
Samantha Coyle, a Software Engineer at Diagrid, specializes in Go for cloud-native developer tooling, abstracting application development challenges. Committed to Open Source, she contributes to projects like Dapr and Testcontainers. She boasts a rich history in retail computer vision solutions and successfully stabilized industrial edge use cases with testing and diverse deployments for biopharma data pipelines. Her expertise extends to being CKAD certified and reviewing Go textbooks. She is passionate about empowering early-career, diverse professionals.Samantha is in a family of gophers, and enjoys GopherCon with her brother and identical twin sister. She's a seasoned speaker, having presented at various conferences, including GopherCon.
Read more
See other products by Samantha Coyle
Getfree access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook?Chevron down iconChevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website?Chevron down iconChevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook?Chevron down iconChevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support?Chevron down iconChevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks?Chevron down iconChevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook?Chevron down iconChevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.


[8]ページ先頭

©2009-2025 Movatter.jp