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.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
Go Cookbook

You're reading from   Go Cookbook Build modular, readable, and testable applications in Go

Arrow left icon
Product type Paperback
Published in Jun 2017
Publisher Packt
ISBN-13 9781783286836
Length 400 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
 Torres Torres
Author Profile Icon Torres
Torres
Arrow right icon
View More author details
Toc

Table of Contents (20) Chapters Close

Title Page
Credits
About the Author
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface
1. I/O and File Systems FREE CHAPTER 2. Command-Line Tools 3. Data Conversion and Composition 4. Error Handling in Go 5. All about Databases and Storage 6. Web Clients and APIs 7. Microservices for Applications in Go 8. Testing 9. Parallelism and Concurrency 10. Distributed Systems 11. Reactive Programming and Data Streams 12. Serverless Programming 13. Performance Improvements, Tips, and Tricks

Using the bytes and strings packages


The bytes and string packages have a number of useful helpers to work with and convert between strings and byte types. They allow the creation of buffers that work with a number of common I/O interfaces.

Getting ready

Refer to the Getting ready section's steps in the Using the common I/O interfaces recipe.

How to do it...

These steps cover writing and running your application:

  1. From your terminal/console application, create a new directory called chapter1/bytestrings.
  2. Navigate to this directory.

  1. Copy tests from https://github.com/agtorre/go-cookbook/tree/master/chapter1/bytesstrings, or use this as an exercise to write some of your own code!
  2. Create a file called buffer.go with the following contents:
        package bytestrings

        import (
                "bytes"
                "io"
                "io/ioutil"
        )

        // Buffer demonstrates some tricks for initializing bytes    
        //Buffers
        // These buffers implement an io.Reader interface
        func Buffer(rawString string) *bytes.Buffer {

                // we'll start with a string encoded into raw bytes
                rawBytes := []byte(rawString)

                // there are a number of ways to create a buffer from 
                // the raw bytes or from the original string
                var b = new(bytes.Buffer)
                b.Write(rawBytes)

                // alternatively
                b = bytes.NewBuffer(rawBytes)

                // and avoiding the intial byte array altogether
                b = bytes.NewBufferString(rawString)

                return b
        }

        // ToString is an example of taking an io.Reader and consuming 
        // it all, then returning a string
        func toString(r io.Reader) (string, error) {
                b, err := ioutil.ReadAll(r)
                if err != nil {
                    return "", err
                }
                return string(b), nil
        }
  1. Create a file called bytes.go with the following contents:
        package bytestrings

        import (
                "bufio"
                "bytes"
                "fmt"
        )

        // WorkWithBuffer will make use of the buffer created by the
        // Buffer function
        func WorkWithBuffer() error {
                rawString := "it's easy to encode unicode into a byte 
                              array"

                b := Buffer(rawString)

                // we can quickly convert a buffer back into byes with
                // b.Bytes() or a string with b.String()
                fmt.Println(b.String())

                // because this is an io Reader we can make use of  
                // generic io reader functions such as
                s, err := toString(b)
                if err != nil {
                    return err
                }
                fmt.Println(s)

                // we can also take our bytes and create a bytes reader
                // these readers implement io.Reader, io.ReaderAt, 
                // io.WriterTo, io.Seeker, io.ByteScanner, and 
                // io.RuneScanner interfaces
                reader := bytes.NewReader([]byte(rawString))

                // we can also plug it into a scanner that allows 
                // buffered reading and tokenzation
                scanner := bufio.NewScanner(reader)
                scanner.Split(bufio.ScanWords)

                // iterate over all of the scan events
                for scanner.Scan() {
                    fmt.Print(scanner.Text())
                }

                return nil
        }
  1. Create a file called string.go with the following contents:
        package bytestrings

        import (
                "fmt"
                "io"
                "os"
                "strings"
        )

        // SearchString shows a number of methods
        // for searching a string
        func SearchString() {
                s := "this is a test"

                // returns true because s contains
                // the word this
                fmt.Println(strings.Contains(s, "this"))

                // returns true because s contains the letter a
                // would also match if it contained b or c
                fmt.Println(strings.ContainsAny(s, "abc"))

                // returns true because s starts with this
                fmt.Println(strings.HasPrefix(s, "this"))

                // returns true because s ends with this
                fmt.Println(strings.HasSuffix(s, "test"))
                }

        // ModifyString modifies a string in a number of ways
        func ModifyString() {
                s := "simple string"

                // prints [simple string]
                fmt.Println(strings.Split(s, " "))

                // prints "Simple String"
                fmt.Println(strings.Title(s))

                // prints "simple string"; all trailing and
                // leading white space is removed
                s = " simple string "
                fmt.Println(strings.TrimSpace(s))
        }

        // StringReader demonstrates how to create
        // an io.Reader interface quickly with a string
        func StringReader() {
                s := "simple stringn"
                r := strings.NewReader(s)

                // prints s on Stdout
                io.Copy(os.Stdout, r)
        }
  1. Create a new directory named example.
  2. Navigate to example.
  3. Create a main.go file with the following contents and ensure that you modify the interfaces imported to use the path you set up in step 2:
        package main

        import "github.com/agtorre/go-cookbook/chapter1/bytestrings"

        func main() {
                err := bytestrings.WorkWithBuffer()
                if err != nil {
                        panic(err)
                }

                // each of these print to stdout
                bytestrings.SearchString()
                bytestrings.ModifyString()
                bytestrings.StringReader() 
        }
  1. Run go run main.go.
  2. You may also run these:
      go build
      ./example

You should see the following output:

        $ go run main.go
        it's easy to encode unicode into a byte array ??
        it's easy to encode unicode into a byte array ??
        it'seasytoencodeunicodeintoabytearray??true
        true
        true
        true
        [simple string]
        Simple String
        simple string
        simple string
  1. If you copied or wrote your own tests, go up one directory and run go test, and ensure all tests pass.

How it works...

The bytes library provides a number of convenience functions when working with data. A buffer, for example, is far more flexible than an array of bytes when working with stream processing libraries or methods. Once you've created a buffer, it can be used to satisfy an io.Reader interface so you can take advantage of ioutil functions to manipulate the data. For steaming applications, you'd probably want to use a buffer and a scanner. The bufio package comes in handy for these cases. Sometimes, using an array or slice is more appropriate for smaller datasets or when you have a lot of memory on your machine.

Go provides a lot of flexibility in converting between interfaces with these basic types--it's relatively simple to convert between strings and bytes. When working with strings, the strings package provides a number of convenience functions to work with, search, and manipulate strings. In some cases, a good regular expression may be appropriate, but most of the time, the strings and strconv packages are sufficient. The strings package allows you to make a string look like a title, split it into an array, or trim whitespace. It also provides a Reader interface of its own that can be used instead of the bytes package reader type.

You have been reading a chapter from
Go Cookbook
Published in: Jun 2017
Publisher: Packt
ISBN-13: 9781783286836
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime
Visually different images