was successfully added to your cart.

Cart

Technology

The most useful string functions in GO

By 7 October, 2021 No Comments

The most useful string functions in GO

The concept of a string exists in all languages and Golang is not the exception.

In this blog, I’m going to show the most useful concepts and functions to work with strings in Golang.

Most of the examples will contain tests, you may be more used to using the Assert keyword to perform checking, but the authors of The Go Programming Language make some good arguments for Go’s style over Assertions

Data type

In Golang, String is a data type, it is not a struct or class. It does not have methods or functions.

Slice of bytes

Different from other languages such as Java, in Golang the strings are not an array of characters, instead, they are an array of bytes that represent UTF-8 encodings. That means you are able to use any kind of human language by default. I am going to show the differences

 
func TestStringSliceBytesUTF8(t *testing.T) {
  got := "Hello 世界 🦊"
  expected := "\x48\x65\x6c\x6c\x6f\x20\xe4\xb8\x96\xe7\x95\x8c\x20\xf0\x9f\xa6\x8a"

  if got != expected {
    t.Errorf("expected %s got %s", expected, got)
  }
}

Immutable

The main difference between string and slice of bytes in GO is the way they are handled in memory. Strings are immutable, you are not able to modify them. If you want to add a new element, you have to create another string.

Package strings

String has no methods to split or get the length, instead, Golang gives up the strings package to manipulate

Golang initializing strings

Basically, you have two ways to create a string.
From string literal

func TestStringLiteral(t *testing.T) {
   got := "Go is Awesome!"
   if got != "Go is Awesome!" {
       t.Errorf("expected %s got %s", "Go is Awesome!", got)
   }
}

From string multiline

func TestStringMultiline(t *testing.T) {
   got := `
   {
       "state":"Awesome",
       "data":[
          {
             "language":"Go"
          }
       ]
    }`
 
   expect := "\n" +
       "\t{\n" +
       "\t\t\"state\":\"Awesome\",\n" +
       "\t\t\"data\":[\n" +
       "\t\t   {\n" +
       "\t\t\t  \"language\":\"Go\"\n" +
       "\t\t   }\n" +
       "\t\t]\n" +
       "\t }"
 
   if got != expect {
       t.Errorf("expected %s got %s", expect, got)
   }
}
 

String length

The length of a string can be obtained using the standard function len(s)

func TestStringLength(t *testing.T) {
 s := "golang"
   if len(s) != 6 {
       t.Error("Error", s)
   }
}

It is important to remember that a string is an array of bytes, the function len(s) is going to return the amount of bytes used. So for non-ASCII characters you are going to obtain something like that:

func TestStringLength(t *testing.T) {
   s := "вишня"
   if len(s) != 10 {
       t.Error("Error", len(s))
   }
 
   s = "🐺🦊🦝"
   if len(s) != 12 {
       t.Error("Error", len(s))
   }
}

Get an element of string

You have to see a string as an array of bytes, so in order to get an element by index do this:

func TestStringElementAt(t *testing.T) {
   myString := "Go is Awesome!"
   //at index 0, it is a byte
   b := myString[0]
 
   //convert byte to rune, rune is a character
   got := rune(b)
 
   expect := 'G'
   if got != expect {
       t.Errorf("expect %c got %c", expect, b)
   }
}

the result is a byte, you need to convert it to a character using rune type. Here is more information about rune type https://golangbyexample.com/understanding-rune-in-golang/

Iterate over a string

The same, you have to see a string as an array of bytes, simply you are able to iterate it

func TestStringIterationWithRange(t *testing.T) {
   nameString := "omar barra"
   for _, v := range namestring {
       fmt.Printf("%q\n", v)
   }
}

Equal String

Go does not provide a function or method to compare two strings, it is not necessary in golang. You can use the operators == or != directly.

func TestStringEqualsCaseSensitive(t *testing.T) {
   got := "Go is Awesome!"
   expect := "Go is Awesome!"
 
   if got != expect {
       t.Errorf("expected %s got %s", expect, got)
   }
 
   if got == "other text" {
       t.Errorf("expected %s got %s", expect, got)
   }
}

Fortunately, Go offers you a function for case-insensitive equality, which is strings.EqualFold, there we go

func TestStringEqualsCaseInsensitive(t *testing.T) {
   got := "Go is Awesome!"
   expect := "go is awesome!"
  
   if !strings.EqualFold(got, expect) {
       t.Errorf("expected %s got %s", expect, got)
   }
}

String concatenation

Simply do this

func TestStringConcat(t *testing.T) {
   result := "First" + "Second"
 
   if result != "FirstSecond" {
       t.Error("Error", result)
   }
}

Remember you are creating a new string and you are allocating a new portion of memory.

strings.Builder

In some use cases, you have to concatenate a variable list of strings. When you have a variable list of strings the most appropriate way to concatenate is using string.Builder. This structure gives you the function to concatenate strings and avoid wasting memory unnecessarily.

func TestStringBuilder(t *testing.T) {
   words := []string{"First", "Second", "Third"}
 
   var builder strings.Builder
 
   for _, w := range words {
       builder.WriteString(w)
   }
 
   result := builder.String()
 
   if result != "FirstSecondThird" {
       t.Error("Error", result)
   }
}

IsBlank

This function is quite useful and many languages, for example, Java provides one. However, Go does not. Here are two ways to do that

 
func TestStringIsBlank(t *testing.T) {
   myString := "\n\n\t\t"
 
   //is blank first option
   if strings.TrimSpace(myString) != "" {
       t.Error("Error ", myString)
   }
 
   //is blank second option
   if len(strings.TrimSpace(myString)) != 0 {
       t.Error("Error ", myString)
   }
}

Removing characters from a string

Sometimes, you need to remove one or more characters from a string. The Go way to do it is:

 
func TestStringRemovingSpace(t *testing.T) {
   myString := "I am Programmer"
   r := strings.Replace(myString, " ", "", -1)
   if r != "IamProgrammer" {
       t.Error("Error", r)
   }
}

This function will replace every space in the string with “”.

A most readily way to do it is using strings.ReplaceAll introduced in GO 1.13

func TestStringRemovingSpace(t *testing.T) {
   myString := "I am Programmer"
   r := strings.ReplaceAll(myString, " ", "")
   if r != "IamProgrammer" {
       t.Error("Error", r)
   }
}

Summing up

Golang’s main goal is to be as simple and powerful as possible. In that way, Go provides the most necessary function to work with string avoiding fancy things such as a function to compare string, function to check string blank.

In this article, I do not cover how to join or split a string, string formatting and other useful functions such as strings.Trim, strings.Prefix, strings.Sufix. but you can find those examples and more in my repository

https://github.com/obarra-dev/poc-golang/blob/master/go-115/string_test.go .

Thanks, see you in the next episode.