One place for hosting & domains

      April 2019

      How To Format Strings in Go


      As strings are often made up of written text, there are many instances when we may want to have greater control over how strings look to make them more readable for humans through punctuation, line breaks, and indentation.

      In this tutorial, we’ll go over some of the ways we can work with Go strings to make sure that all output text is formatted correctly.

      String Literals

      Let’s first differentiate between a string literal and a string value. A string literal is what we see in the source code of a computer program, including the quotation marks. A string value is what we see when we call the fmt.Println function and run the program.

      In the “Hello, World!” program, the string literal is "Hello, World!" while the string value is Hello, World! without the quotation marks. The string value is what we see as the output in a terminal window when we run a Go program.

      But some string values may need to include quotation marks, like when we are quoting a source. Because string literals and string values are not equivalent, it is often necessary to add additional formatting to string literals to ensure that string values are displayed the way in which we intend.

      Quotes

      Because we can use back quotes (`) or double quotes (") within Go, it is simple to embed quotes within a string by using double quotes within a string enclosed by back quotes:

      `Sammy says, "Hello!"`
      

      Or, to use a back quote, you can enclose the string in double quotes:

      "Sammy likes the `fmt` package for formatting strings.."
      

      In the way we combine back quotes and double quotes, we can control the display of quotation marks and back quotes within our strings.

      It’s important to remember that using back quotes in Go creates a raw string literal, and using double quotes creates an interpreted string literal. To learn more about the difference, read the An Introduction to Working with Strings in Go tutorial.

      Escape Characters

      Another way to format strings is to use an escape character. Escape characters are used to tell the code that the following character has a special meaning. Escape characters all start with the backslash key () combined with another character within a string to format the given string a certain way.

      Here is a list of several of the common escape characters:

      Escape CharacterHow it formats
      \Backslash
      Double Quote
      nLine Break
      tTab (horizontal indentation)

      Let’s use an escape character to add the quotation marks to the example on quotation marks above, but this time we’ll use double quotes to denote the string:

      fmt.Println("Sammy says, "Hello!"")
      

      Output

      Sammy says, "Hello!"

      By using the escape character " we are able to use double quotes to enclose a string that includes text quoted between double quotes.

      We can use the n escape character to break lines without hitting the enter or return key:

      fmt.Println("This stringnspans multiplenlines.")
      

      Output

      This string spans multiple lines.

      We can combine escape characters, too. Let’s print a multi-line string and include tab spacing for an itemized list, for example:

      fmt.Println("1.tSharkn2.tShrimpn10.tSquid")
      

      Output

      1. Shark 2. Shrimp 10. Squid

      The horizontal indentation provided with the t escape character ensures alignment within the second column in the preceding example, making the output extremely readable for humans.

      Escape characters are used to add additional formatting to strings that may be difficult or impossible to achieve. Without escape characters, you would not be able to construct the string Sammy says, "I like to use the `fmt` package".

      Multiple Lines

      Printing strings on multiple lines can make text more readable to humans. With multiple lines, strings can be grouped into clean and orderly text, formatted as a letter, or used to maintain the linebreaks of a poem or song lyrics.

      To create strings that span multiple lines, back quotes are used to enclose the string. Keep in mind that while this will preserve the line returns, it is also creating a raw string literal.

      `
      This string is on 
      multiple lines
      within three single 
      quotes on either side.
      `
      

      You will notice if you print this that there is a leading and trailing return:

      Output

      This string is on multiple lines within three single quotes on either side.

      To avoid this, you need to put the first line immediately following the back quote and end the last with the back quote.

      `This string is on 
      multiple lines
      within three single 
      quotes on either side.`
      

      If you need to create an interpreted string literal, this can be done with double quotes and the + operator, but you will need to insert your own line breaks.

      "This string is onn" +
      "multiple linesn" +
      "within three singlen" +
      "quotes on either side."
      

      While back quotes can make it easier to print and read lengthy text, if you need an interpreted string literal, you will need to use double quotes.

      Raw String Literals

      What if we don’t want special formatting within our strings? For example, we may need to compare or evaluate strings of computer code that use the backslash on purpose, so we won’t want Go to use it as an escape character.

      A raw string literal tells Go to ignore all formatting within a string, including escape characters.

      We create a raw string by using back quotes around the string:

      fmt.Println(`Sammy says,"The balloon's color is red."`)
      

      Output

      Sammy says,"The balloon's color is red."

      By constructing a raw string by using back quotes around a given string, we can retain backslashes and other characters that are used as escape characters.

      Conclusion

      This tutorial went over several ways to format text in Go through working with strings. By using techniques such as escape characters or raw strings, we are able to ensure that the strings of our program are rendered correctly on-screen so that the end user is able to easily read all of the output text.



      Source link

      Understanding Maps in Go


      Most modern programming languages have the concept of a dictionary or a hash type. These types are commonly used to store data in pairs with a key that maps to a value.

      In Go, the map data type is what most programmers would think of as the dictionary type. It maps keys to values, making key-value pairs that are a useful way to store data in Go. A map is constructed by using the keyword map followed by the key data type in square brackets [ ], followed by the value data type. The key-value pairs are then placed inside curly braces on either side { }:

      map[key]value{}
      

      You typically use maps in Go to hold related data, such as the information contained in an ID. A map with data looks like this:

      map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
      

      In addition to the curly braces, there are also colons throughout the map that connect the key-value pairs. The words to the left of the colons are the keys. Keys can be any comparable type in Go, like strings, ints, and so on.

      The keys in the example map are:

      • "name"
      • "animal"
      • "color"
      • "location"

      The words to the right of the colons are the values. Values can be any data type. The values in the example map are:

      • "Sammy"
      • "shark"
      • "blue"
      • "ocean"

      Like the other data types, you can store the map inside a variable, and print it out:

      sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
      fmt.Println(sammy)
      

      This would be your output:

      Output

      map[animal:shark color:blue location:ocean name:Sammy]

      The order of the key-value pairs may have shifted. In Go, the map data type is unordered. Regardless of the order, the key-value pairs will remain intact, enabling you to access data based on their relational meaning.

      Accessing Map Items

      You can call the values of a map by referencing the related keys. Since maps offer key-value pairs for storing data, they can be important and useful items in your Go program.

      If you want to isolate Sammy’s username, you can do so by calling sammy["name"]; the variable holding your map and the related key. Let’s print that out:

      fmt.Println(sammy["name"])
      

      And receive the value as output:

      Output

      Sammy

      Maps behave like a database; instead of calling an integer to get a particular index value as you would with a slice, you assign a value to a key and call that key to get its related value.

      By invoking the key "name" you receive the value of that key, which is "Sammy".

      Similarly you can call the remaining values in the sammy map using the same format:

      fmt.Println(sammy["animal"])
      // returns shark
      
      fmt.Println(sammy["color"])
      // returns blue
      
      fmt.Println(sammy["location"])
      // returns ocean
      

      By making use of the key-value pairs in map data types, you can reference keys to retrieve values.

      Keys and Values

      Unlike some programming languages, Go does not have any convenience functions to list out the keys or values of a map. An example of this would be Python’s .keys() method for dictionaries. It does, however, allow for iteration by using the range operator:

      for key, value := range sammy {
          fmt.Printf("%q is the key for the value %qn", key, value)
      }
      

      When ranging through a map in Go, it’ll return two values. The first value will be the key, and the second value will be the value. Go will create these variables with the correct data type. In this case, the map key was a string so key will also be a string. The value is also a string:

      Output

      "animal" is the key for the value "shark" "color" is the key for the value "blue" "location" is the key for the value "ocean" "name" is the key for the value "Sammy"

      To get a list of just the keys, you can use the range operator again. You can declare just one variable to only access the keys:

      keys := []string{}
      
      for key := range sammy {
          keys = append(keys, key)
      }
      fmt.Printf("%q", keys)
      

      The program begins by declaring a slice to store your keys in.

      The output will show only the keys of your map:

      Output

      ["color" "location" "name" "animal"]

      Again, the keys are not sorted. If you want to sort them, you use the sort.Strings function from the sort package:

      sort.Strings(keys)
      

      With this function, you’ll receive the following output:

      Output

      ["animal" "color" "location" "name"]

      You can use the same pattern to retrieve just the values in a map. In the next example, you pre-allocate the slice to avoid allocations, thus making the program more efficient:

      sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
      
      items := make([]string, len(sammy))
      
      var i int
      
      for _, v := range sammy {
          items[i] = v
          i++
      }
      fmt.Printf("%q", items)
      

      First you declare a slice to store your keys in; since you know how many items you need, you can avoid potential memory allocations by defining the slice at the exact same size. You then declare your index variable. As you don’t want the key, you use the _ operator, when starting your loop, to ignore the key’s value. Your output would be the following:

      Output

      ["ocean" "Sammy" "shark" "blue"]

      To determine the number of items in a map, you can use the built-in len function:

      sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
      fmt.Println(len(sammy))
      

      The output displays the number of items in your map:

      Output

      4

      Even though Go doesn’t ship with convenience functions to get keys and values, it only takes a few lines of code to retrieve the keys and values when needed.

      Checking Existence

      Maps in Go will return the zero value for the value type of the map when the requested key is missing. Because of this, you need an alternative way to differentiate a stored zero, versus a missing key.

      Let’s look up a value in a map that you know doesn’t exist and look at the value returned:

      counts := map[string]int{}
      fmt.Println(counts["sammy"])
      

      You’ll see the following output:

      Output

      0

      Even though the key sammy was not in the map, Go still returned the value of 0. This is because the value data type is an int, and because Go has a zero value for all variables, it returns the zero value of 0.

      In many cases, this is undesirable and would lead to a bug in your program. When looking up the value in a map, Go can return a second, optional value. This second value is a bool and will be true if the key was found, or false if the key was not found. In Go, this is referred to as the ok idiom. Even though you could name the variable that captures the second argument anything you want, in Go, you always name it ok:

      count, ok := counts["sammy"]
      

      If the key sammy exists in the counts map, then ok will be true. Otherwise ok will be false.

      You can use the ok variable to decide what to do in your program:

      if ok {
          fmt.Printf("Sammy has a count of %dn", count)
      } else {
          fmt.Println("Sammy was not found")
      }
      

      This would result in the following output:

      Output

      Sammy was not found

      In Go, you can combine variable declaration and conditional checking with an if/else block. This allows you to use a single statement for this check:

      if count, ok := counts["sammy"]; ok {
          fmt.Printf("Sammy has a count of %dn", count)
      } else {
          fmt.Println("Sammy was not found")
      }
      

      When retrieving a value from a map in Go, it’s always good practice to check for its existence as well to avoid bugs in your program.

      Modifying Maps

      Maps are a mutable data structure, so you can modify them. Let’s look at adding and deleting map items in this section.

      Adding and Changing Map Items

      Without using a method or function, you can add key-value pairs to maps. You do this using the maps variable name, followed by the key value in square brackets [ ], and using the equal = operator to set a new value:

      map[key] = value
      

      In practice, you can see this work by adding a key-value pair to a map called usernames:

      usernames := map[string]string{"Sammy": "sammy-shark", "Jamie": "mantisshrimp54"}
      
      usernames["Drew"] = "squidly"
      fmt.Println(usernames)
      

      The output will display the new Drew:squidly key-value pair in the map:

      Output

      map[Drew:squidly Jamie:mantisshrimp54 Sammy:sammy-shark]

      Because maps are returned unordered, this pair may occur anywhere in the map output. If you use the usernames map later in your program file, it will include the additional key-value pair.

      You can also use this syntax for modifying the value assigned to a key. In this case, you reference an existing key and pass a different value to it.

      Consider a map called followers that tracks followers of users on a given network. The user "drew" had a bump in followers today, so you need to update the integer value passed to the "drew" key. You’ll use the Println() function to check that the map was modified:

      followers := map[string]int{"drew": 305, "mary": 428, "cindy": 918}
      followers["drew"] = 342
      fmt.Println(followers)
      

      Your output will show the updated value for drew:

      Output

      map[cindy:918 drew:342 mary:428]

      You see that the number of followers jumped from the integer value of 305 to 342.

      You can use this method for adding key-value pairs to maps with user input. Let’s write a quick program called usernames.go that runs on the command line and allows input from the user to add more names and associated usernames:

      usernames.go

      package main
      
      import (
          "fmt"
          "strings"
      )
      
      func main() {
          usernames := map[string]string{"Sammy": "sammy-shark", "Jamie": "mantisshrimp54"}
      
          for {
              fmt.Println("Enter a name:")
      
              var name string
              _, err := fmt.Scanln(&name)
      
              if err != nil {
                  panic(err)
              }
      
              name = strings.TrimSpace(name)
      
              if u, ok := usernames[name]; ok {
                  fmt.Printf("%q is the username of %qn", u, name)
                  continue
              }
      
              fmt.Printf("I don't have %v's username, what is it?n", name)
      
              var username string
              _, err = fmt.Scanln(&username)
      
              if err != nil {
                  panic(err)
              }
      
              username = strings.TrimSpace(username)
      
              usernames[name] = username
      
              fmt.Println("Data updated.")
          }
      }
      

      In usernames.go you first define the original map. You then set up a loop to iterate over the names. You request your user to enter a name and declare a variable to store it in. Next, you check to see if you had an error; if so, the program will exit with a panic. Because Scanln captures the entire input, including the carriage return, you need to remove any space from the input; you do this with the strings.TrimSpace function.

      The if block checks whether the name is present in the map and prints feedback. If the name is present it then continues back to the top of the loop. If the name is not in the map, it provides feedback to the user and then will ask for a new username for the associated name. The program checks again to see if there is an error. With no error, it trims off the carriage return, assigns the username value to the name key, and then prints feedback that the data was updated.

      Let’s run the program on the command line:

      You'll see the following output:

      Output

      Enter a name: Sammy "sammy-shark" is the username of "Sammy" Enter a name: Jesse I don't have Jesse's username, what is it? JOctopus Data updated. Enter a name:

      When you're done testing, press CTRL + C to escape the program.

      This shows how you can modify maps interactively. With this particular program, as soon as you exit the program with CTRL + C you’ll lose all your data unless you implement a way to handle reading and writing files.

      To summarize, you can add items to maps or modify values with the map[key] = value syntax.

      Deleting Map Items

      Just as you can add key-value pairs and change values within the map data type, you can also delete items within a map.

      To remove a key-value pair from a map, you can use the built-in function delete(). The first argument is the map you are deleting from. The second argument is the key you are deleting:

      delete(map, key)
      

      Let's define a map of permissions:

      permissions := map[int]string{1: "read", 2: "write", 4: "delete", 8: "create", 16:"modify"}
      

      You no longer need the modify permission, so you'll remove it from your map. Then you'll print out the map to confirm it was removed:

      permissions := map[int]string{1: "read", 2: "write", 4: "delete", 8: "create", 16: "modify"}
      delete(permissions, 16)
      fmt.Println(permissions)
      

      The output will confirm the deletion:

      Output

      map[1:read 2:write 4:delete 8:create]

      The line delete(permissions, 16) removes the key-value pair 16:"modify" from the permissions map.

      If you would like to clear a map of all of its values, you can do so by setting it equal to an empty map of the same type. This will create a new empty map to use, and the old map will be cleared from memory by the garbage collector.

      Let’s remove all the items within the permissions map:

      permissions = map[int]string{}
      fmt.Println(permissions)
      

      The output shows that you now have an empty map devoid of key-value pairs:

      Output

      map[]

      Because maps are mutable data types, they can be added to, modified, and have items removed and cleared.

      Conclusion

      This tutorial explored the map data structure in Go. Maps are made up of key-value pairs and provide a way to store data without relying on indexing. This allows us to retrieve values based on their meaning and relation to other data types.



      Source link

      An Introduction to Working with Strings in Go


      A string is a sequence of one or more characters (letters, numbers, symbols) that can be either a constant or a variable. Made up of Unicode, strings are immutable sequences, meaning they are unchanging.

      Because text is such a common form of data that we use in everyday life, the string data type is a very important building block of programming.

      This Go tutorial will go over how to create and print strings, how to concatenate and replicate strings, and how to store strings in variables.

      String Literals

      In Go, strings exist within either back quotes ` (sometimes referred to as back ticks) or double quotes ". Depending on which quotes you use, the string will have different characteristics.

      Using back quotes, as in `bar`, will create a raw string literal. In a raw string literal, any character may appear between quotes, with the exception of back quotes. Here’s an example of a raw string literal:

      `Say "hello" to Go!`
      

      Backslashes have no special meaning inside of raw string literals. For instance, n will appear as the actual characters, backslash and letter n. Unlike interpreted string literals, in which n would insert an actual new line.

      Raw string literals may also be used to create multi-line strings:

      `Go is expressive, concise, clean, and efficient.
      Its concurrency mechanisms make it easy to write programs
      that get the most out of multi-core and networked machines,
      while its novel type system enables flexible and modular
      program construction. Go compiles quickly to machine code
      yet has the convenience of garbage collection and the power
      of run-time reflection. It's a fast, statically typed,
      compiled language that feels like a dynamically typed,
      interpreted language.`
      

      Interpreted string literals are character sequences between double quotes, as in "bar". Within the quotes, any character may appear with the exception of newline and unescaped double quotes.

      "Say "hello" to Go!"
      

      You will almost always use interpreted string literals because they allow for escape characters within them.

      Now that you understand how strings are formatted in Go, let’s take a look at how you can print strings in programs.

      Printing Strings

      You can print out strings by using the fmt package from the system library and calling the Println() function:

      fmt.Println("Let's print out this string.")
      

      Output

      Let's print out this string.

      You have to import system packages when you use them, so a simple program to print out a string would look like this:

      package main
      
      import "fmt"
      
      func main() {
          fmt.Println("Let's print out this string.")
      }
      

      String Concatenation

      Concatenation means joining strings together, end-to-end, to create a new string. You can concatenate strings with the + operator. Keep in mind that when you work with numbers, + will be an operator for addition, but when used with strings it is a joining operator.

      Let’s combine the string literals "Sammy" and "Shark" together with concatenation through a fmt.Println() statement:

      fmt.Println("Sammy" + "Shark")
      

      Output

      SammyShark

      If you would like a whitespace between the two strings, you can simply include the whitespace within a string. In this example, add the whitespace within the quotes after Sammy:

      fmt.Println("Sammy " + "Shark")
      

      Output

      Sammy Shark

      The + operator can not be used between two different data types. As an example, you can’t concatenate strings and integers together. If you were to try to write the following:

      fmt.Println("Sammy" + 27)
      

      You will receive the following errors:

      Output

      cannot convert "Sammy" (type untyped string) to type int invalid operation: "Sammy" + 27 (mismatched types string and int)

      If you wanted to create the string "Sammy27", you could do so by putting the number 27 in quotes ("27") so that it is no longer an integer but is instead a string. Converting numbers to strings for concatenation can be useful when dealing with zip codes or phone numbers. For example, you wouldn’t want to perform addition between a country code and an area code, but you do want them to stay together.

      When you combine two or more strings through concatenation, you are creating a new string that you can use throughout your program.

      Storing Strings in Variables

      Variables are symbols that you can use to store data in a program. You can think of them as an empty box that you fill with some data or value. Strings are data, so you can use them to fill up a variable. Declaring strings as variables can make it easier to work with strings throughout your Go programs.

      To store a string inside a variable, simply assign a variable to a string. In this case, declare s as your variable:

      s := "Sammy likes declaring strings."
      

      Note: If you’re familiar with other programming languages, you may have written the variable as sammy. Go, however, favors shorter variable names. Choosing s for the variable name in this case would be considered more appropriate for the style in which Go is written.

      Now that you have the variable s set to that particular string, you can print the variable like so:

      fmt.Println(s)
      

      You will then receive the following output:

      Output

      Sammy likes declaring strings.

      By using variables to stand in for strings, you do not have to retype a string each time you want to use it, making it more simple for you to work with and manipulate strings within your programs.

      Conclusion

      This tutorial went over the basics of working with the string data type in the Go programming language. Creating and printing strings, concatenating and replicating strings, and storing strings in variables will provide you with the fundamentals to use strings in your Go programs.



      Source link