86 lines
3.4 KiB
Go
86 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
)
|
|
|
|
// Strings in Go allow arbitrary bytes. They are implemented basically as
|
|
// immutable byte slices and syntactic sugar. This program shows functions
|
|
// required by the task on byte slices, thus it mostly highlights what
|
|
// happens behind the syntactic sugar. The program does not attempt to
|
|
// reproduce the immutability property of strings, as that does not seem
|
|
// to be the intent of the task.
|
|
|
|
func main() {
|
|
// Task point: String creation and destruction.
|
|
// Strings are most often constructed from literals as in s := "binary"
|
|
// With byte slices,
|
|
b := []byte{'b', 'i', 'n', 'a', 'r', 'y'}
|
|
fmt.Println(b) // output shows numeric form of bytes.
|
|
// Go is garbage collected. There are no destruction operations.
|
|
|
|
// Task point: String assignment.
|
|
// t = s assigns strings. Since strings are immutable, it is irrelevant
|
|
// whether the string is copied or not.
|
|
// With byte slices, the same works,
|
|
var c []byte
|
|
c = b
|
|
fmt.Println(c)
|
|
|
|
// Task point: String comparison.
|
|
// operators <, <=, ==, >=, and > work directly on strings comparing them
|
|
// by lexicographic order.
|
|
// With byte slices, there are standard library functions, bytes.Equal
|
|
// and bytes.Compare.
|
|
fmt.Println(bytes.Equal(b, c)) // prints true
|
|
|
|
// Task point: String cloning and copying.
|
|
// The immutable property of Go strings makes cloning and copying
|
|
// meaningless for strings.
|
|
// With byte slices though, it is relevant. The assignment c = b shown
|
|
// above does a reference copy, leaving both c and b based on the same
|
|
// underlying data. To clone or copy the underlying data,
|
|
d := make([]byte, len(b)) // allocate new space
|
|
copy(d, b) // copy the data
|
|
// The data can be manipulated independently now:
|
|
d[1] = 'a'
|
|
d[4] = 'n'
|
|
fmt.Println(string(b)) // convert to string for readable output
|
|
fmt.Println(string(d))
|
|
|
|
// Task point: Check if a string is empty.
|
|
// Most typical for strings is s == "", but len(s) == 0 works too.
|
|
// For byte slices, "" does not work, len(b) == 0 is correct.
|
|
fmt.Println(len(b) == 0)
|
|
|
|
// Task point: Append a byte to a string.
|
|
// The language does not provide a way to do this directly with strings.
|
|
// Instead, the byte must be converted to a one-byte string first, as in,
|
|
// s += string('z')
|
|
// For byte slices, the language provides the append function,
|
|
z := append(b, 'z')
|
|
fmt.Printf("%s\n", z) // another way to get readable output
|
|
|
|
// Task point: Extract a substring from a string.
|
|
// Slicing syntax is the for both strings and slices.
|
|
sub := b[1:3]
|
|
fmt.Println(string(sub))
|
|
|
|
// Task point: Replace every occurrence of a byte (or a string)
|
|
// in a string with another string.
|
|
// Go supports this with similar library functions for strings and
|
|
// byte slices. Strings: t = strings.Replace(s, "n", "m", -1).
|
|
// The byte slice equivalent returns a modified copy, leaving the
|
|
// original byte slice untouched,
|
|
f := bytes.Replace(d, []byte{'n'}, []byte{'m'}, -1)
|
|
fmt.Printf("%s -> %s\n", d, f)
|
|
|
|
// Task point: Join strings.
|
|
// Using slicing syntax again, with strings,
|
|
// rem := s[:1] + s[3:] leaves rem == "bary".
|
|
// Only the concatenation of the parts is different with byte slices,
|
|
rem := append(append([]byte{}, b[:1]...), b[3:]...)
|
|
fmt.Println(string(rem))
|
|
}
|