<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="default.xsl"?>
<fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="true"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>337</fr:anchor><fr:addr
type="user">go-00sx</fr:addr><fr:route>go-00sx.xml</fr:route><fr:title
text="Golang › Difference between maps and slices"><fr:link
type="local"
href="go-00rs.xml"
addr="go-00rs"
title="Golang">Golang</fr:link> › Difference between maps and slices</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Within the go runtime, a map is implemented as a pointer to a struct, so passing a map to a function means that you are copying a pointer. Thus changes made to a map within the functions are reflected in the original.</fr:p><fr:p>**NOTE**: maps for input parameters or return values should be carefully considered. On an API design level, they are a bad choice because they say nothing about the values contained within. In general one should prefer a struct for these cases.</fr:p><fr:p>A slice is more complicated. Any modification to a slices contents within a function is reflected in the original, but using append to change the length of the array is not, even if the slice has a capacity greater than its length. This is due to slice being implemented a struct with three fields:</fr:p><fr:ul><fr:li><fr:code>int</fr:code> for length</fr:li>
<fr:li><fr:code>int</fr:code> for capcity</fr:li>
<fr:li>a pointer to a block of memory</fr:li></fr:ul></fr:mainmatter><fr:backmatter><fr:tree
toc="false"
numbered="false"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:title
text="Context">Context</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:tree
toc="true"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>338</fr:anchor><fr:addr
type="user">go-00rs</fr:addr><fr:route>go-00rs.xml</fr:route><fr:title
text="Golang">Golang</fr:title><fr:taxon>Language</fr:taxon><fr:authors /></fr:frontmatter><fr:mainmatter><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>262</fr:anchor><fr:addr
type="user">go-00rv</fr:addr><fr:route>go-00rv.xml</fr:route><fr:title
text="Initialize module">Initialize module</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Within a new directory, initialize a module with</fr:p><fr:pre><![CDATA[go mod init your/module]]></fr:pre><fr:p>This will create a new file `go.mod`</fr:p></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>263</fr:anchor><fr:addr
type="user">go-00rx</fr:addr><fr:route>go-00rx.xml</fr:route><fr:title
text="Types">Types</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  
  
  <html:tr>
    
  <html:td><fr:strong>Zero:</fr:strong></html:td>

    
  <html:td>Predeclared</html:td>

    
  <html:td>Default value assigned to declared but unassigned variables</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>Literals:</fr:strong></html:td>

    
  <html:td>Predeclared</html:td>

    
  <html:td>Explicitly specified values</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>Integer:</fr:strong></html:td>

    
  <html:td>Literals</html:td>

    
  <html:td>Base 10 by default</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>Floating-point:</fr:strong></html:td>

    
  <html:td>Literals</html:td>

    
  <html:td>Uses decimal point for fractions</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>Rune:</fr:strong></html:td>

    
  <html:td>Literals</html:td>

    
  <html:td>Single character representation</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>String:</fr:strong></html:td>

    
  <html:td>Literals</html:td>

    
  <html:td>Two creation methods</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>Booleans:</fr:strong></html:td>

    
  <html:td>Predeclared</html:td>

    
  <html:td>Binary true/false values</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>byte:</fr:strong></html:td>

    
  <html:td>Integer</html:td>

    
  <html:td>Alias for uint8</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>int:</fr:strong></html:td>

    
  <html:td>Integer</html:td>

    
  <html:td>Signed integer sized to architecture's word size</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>uint:</fr:strong></html:td>

    
  <html:td>Integer</html:td>

    
  <html:td>Unsigned integer sized to architecture's word size</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>rune:</fr:strong></html:td>

    
  <html:td>Integer</html:td>

    
  <html:td>Alias for int32</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>uintptr:</fr:strong></html:td>

    
  <html:td>Integer</html:td>

    
  <html:td>Integer type for storing pointer values</html:td>

  </html:tr>


  
  
  <html:tr>
    
  <html:td><fr:strong>String:</fr:strong></html:td>

    
  <html:td>Predeclared</html:td>

    
  <html:td>Immutable sequence of bytes, zero value is empty string</html:td>

  </html:tr>


</html:table>
</fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>264</fr:anchor><fr:addr
type="user">go-00ry</fr:addr><fr:route>go-00ry.xml</fr:route><fr:title
text="Type conversion">Type conversion</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Go does not support automatic type conversion. All variable types need to be converted to interact.</fr:p><fr:pre><![CDATA[var x int = 10
var y float64 = 30.2
var sum1 float64 = float64(x) + y
var sum2 int = x + int(y)
fmt.Println(sum1, sum2) // 40.2  40]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>265</fr:anchor><fr:addr
type="user">go-00rz</fr:addr><fr:route>go-00rz.xml</fr:route><fr:title
text="Quotes">Quotes</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Different qoutes are used for different contexts.</fr:p><fr:p>The double qoute <fr:code>"</fr:code> will be used to create string literals, while the backtick is used to create <fr:em>raw</fr:em> string literals. The single qoute <fr:code>'</fr:code> is used to create runes, a single unicode point. E.g. <fr:code>r := '學'</fr:code>.</fr:p></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>266</fr:anchor><fr:addr
type="user">go-00s0</fr:addr><fr:route>go-00s0.xml</fr:route><fr:title
text="Slices">Slices</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:ul><fr:li>Slices will have a zero value of <fr:code>nil</fr:code> and is only comprable with <fr:code>nil</fr:code> and <fr:code>==</fr:code>.</fr:li>
    <fr:li>Modifying shared slices will affect all references.</fr:li>
    <fr:li>Length can differ from capacity</fr:li></fr:ul><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>267</fr:anchor><fr:addr
type="user">go-00s3</fr:addr><fr:route>go-00s3.xml</fr:route><fr:title
text="Creation">Creation</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:pre><![CDATA[var s []int             // nil slice
s := []int{1, 2, 3}     // slice literal
s := make([]int, 5)     // length 5, capacity 5
s := make([]int, 0, 10) // length 0, capacity 10]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>268</fr:anchor><fr:addr
type="user">go-00s4</fr:addr><fr:route>go-00s4.xml</fr:route><fr:title
text="Modification">Modification</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:pre><![CDATA[s = append(s, 10)           // single element
s = append(s, 1, 2, 3)      // multiple elements
s = append(s, other...)     // append slice
clear(s)                    // zero all elements (Go 1.21+)]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>269</fr:anchor><fr:addr
type="user">go-00s5</fr:addr><fr:route>go-00s5.xml</fr:route><fr:title
text="Slicing">Slicing</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:pre><![CDATA[s[low:high]     // items low through high-1
s[low:]         // items low through end
s[:high]        // items beginning through high-1
s[:]            // copy of entire slice
s[low:high:max] // control capacity of new slice]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>270</fr:anchor><fr:addr
type="user">go-00s6</fr:addr><fr:route>go-00s6.xml</fr:route><fr:title
text="Copying">Copying</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:pre><![CDATA[copy(dest, src)        // copies min(len(dest), len(src)) elements
copy(dest, src[1:])    // copy from middle of src]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>271</fr:anchor><fr:addr
type="user">go-00s7</fr:addr><fr:route>go-00s7.xml</fr:route><fr:title
text="Array Conversion">Array Conversion</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:pre><![CDATA[array := [4]int{1, 2, 3, 4}
slice := array[:]              // array to slice
array2 := [4]int(slice)       // slice to array (new memory)
arrayPtr := (*[4]int)(slice)  // slice to array pointer (shared memory)]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>272</fr:anchor><fr:addr
type="user">go-00s9</fr:addr><fr:route>go-00s9.xml</fr:route><fr:title
text="When to Use What">When to Use What</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>1.  `var` declaration (nil slice): When size unknown, no initial data 2.  Slice literal: When starting values are known 3.  `make`:     -   With length: For buffers or exact size known     -   Zero length + capacity: For growing slices</fr:p></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>273</fr:anchor><fr:addr
type="user">go-00sa</fr:addr><fr:route>go-00sa.xml</fr:route><fr:title
text="Memory Management">Memory Management</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>-   Capacity doubles when &amp;lt; 256 -   Growth slows to ~25/for larger slices -   Use full slice expression `s[low:high:max]` to prevent capacity issues -   Be careful with shared memory when slicing</fr:p></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>274</fr:anchor><fr:addr
type="user">go-00sb</fr:addr><fr:route>go-00sb.xml</fr:route><fr:title
text="Standard Library">Standard Library</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>-   `slices.Equal(a, b)`: Compare if length and elements match -   `slices.EqualFunc(a, b, fn)`: Custom comparison function</fr:p></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>275</fr:anchor><fr:addr
type="user">go-00sc</fr:addr><fr:route>go-00sc.xml</fr:route><fr:title
text="Maps">Maps</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Maps are declared as `map[keyType]valueType`. A `nil` map (e.g., `var m map[string]int`) cannot be written to. Use `make` or a map literal for writable maps.</fr:p><fr:pre><![CDATA[// Map literal
m := map[string]int{"Alice": 10, "Bob": 20}

// Using make
m := make(map[string]int, 10) // Capacity 10
m["Charlie"] = 30]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>276</fr:anchor><fr:addr
type="user">go-00sd</fr:addr><fr:route>go-00sd.xml</fr:route><fr:title
text="Structs">Structs</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Structs are user-defined types with fields. Define them with `type` and access fields using dot notation.</fr:p><fr:pre><![CDATA[type Person struct {
    Name string
    Age  int
}
p := Person{Name: "Alice", Age: 30}
fmt.Println(p.Name)]]></fr:pre><fr:p>Anonymous structs are inline struct definitions:</fr:p><fr:pre><![CDATA[pet := struct {
    Name string
    Kind string
}{Name: "Fido", Kind: "dog"}]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>277</fr:anchor><fr:addr
type="user">go-00se</fr:addr><fr:route>go-00se.xml</fr:route><fr:title
text="Pointers">Pointers</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Use `&amp;` to get a pointer and `*` to dereference. `nil` pointers cannot be dereferenced.</fr:p><fr:pre><![CDATA[x := 10
p := &x
fmt.Println(*p) // 10]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>278</fr:anchor><fr:addr
type="user">go-00sf</fr:addr><fr:route>go-00sf.xml</fr:route><fr:title
text="Shadowing">Shadowing</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Inner-scope variables can shadow outer-scope ones:</fr:p><fr:pre><![CDATA[x := 10
if x > 5 {
    x := 5
    fmt.Println(x) // 5
}
fmt.Println(x) // 10]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>279</fr:anchor><fr:addr
type="user">go-00sg</fr:addr><fr:route>go-00sg.xml</fr:route><fr:title
text="Control Flow">Control Flow</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>280</fr:anchor><fr:addr
type="user">go-00sh</fr:addr><fr:route>go-00sh.xml</fr:route><fr:title
text="If">If</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Go's `if` statements do not require parentheses. You can declare variables scoped to the condition:</fr:p><fr:pre><![CDATA[if n := rand.Intn(10); n > 5 {
    fmt.Println("Big:", n)
} else {
    fmt.Println("Small:", n)
}]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>281</fr:anchor><fr:addr
type="user">go-00si</fr:addr><fr:route>go-00si.xml</fr:route><fr:title
text="For">For</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Loops in go support complete (C-style), condition only, for-range styles.</fr:p><fr:pre><![CDATA[// C-style
for i := 0; i < 10; i++ {
    fmt.Println(i)
}

// condition only (while)
i := 1
for i < 10 {
    fmt.Println(i)
    i++
}

// for-range
nums := []int{1, 2, 3}
for i, v := range nums {
    fmt.Println(i, v)
}]]></fr:pre><fr:p>If you don't need the key/index in,  the underscore <fr:code>_</fr:code> can be used, telling go to ignore the value.</fr:p><fr:pre><![CDATA[evenVals := []int{2, 4, 6, 8, 10, 12}
for _, v := range evenVals {
    fmt.Printf("%d ", v)
}]]></fr:pre><fr:p>If you just need the key/index, you can leave off the second variable:</fr:p><fr:pre><![CDATA[uniqueNames := map[string]bool{"Fred": true, "Raul": true, "Wilma": true}
for k := range uniqueNames {
    fmt.Printf("%s ", k)
}]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>282</fr:anchor><fr:addr
type="user">go-00sj</fr:addr><fr:route>go-00sj.xml</fr:route><fr:title
text="Switch">Switch</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:pre><![CDATA[words := []string{"a", "cow", "smile", "gopher",
    "octopus", "anthropologist"}
for _, word := range words {
    switch size := len(word); size {
    case 1, 2, 3, 4:
        fmt.Println(word, "is a short word!")
    case 5:
        wordLen := len(word)
        fmt.Println(word, "is exactly the right length:", wordLen)
    case 6, 7, 8, 9:
    default:
        fmt.Println(word, "is a long word!")
    }
}]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>283</fr:anchor><fr:addr
type="user">go-00sk</fr:addr><fr:route>go-00sk.xml</fr:route><fr:title
text="Functions">Functions</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>284</fr:anchor><fr:addr
type="user">go-00sl</fr:addr><fr:route>go-00sl.xml</fr:route><fr:title
text="Variadic Parameters">Variadic Parameters</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Variadic functions accept a variable number of arguments as a slice:</fr:p><fr:pre><![CDATA[func addTo(base int, vals ...int) []int {
    out := make([]int, 0, len(vals))
    for _, v := range vals {
        out = append(out, base+v)
    }
    return out
}]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>285</fr:anchor><fr:addr
type="user">go-00sm</fr:addr><fr:route>go-00sm.xml</fr:route><fr:title
text="Multiple Return Values">Multiple Return Values</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Functions can return multiple values, often used with errors:</fr:p><fr:pre><![CDATA[func divAndRemainder(num, denom int) (int, int, error) {
    if denom == 0 {
        return 0, 0, errors.New("cannot divide by zero")
    }
    return num / denom, num % denom, nil
}]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>286</fr:anchor><fr:addr
type="user">go-00sn</fr:addr><fr:route>go-00sn.xml</fr:route><fr:title
text="Named return values">Named return values</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Functions can have names specified for the return values, which predeclares variables that are used within the function to hold the return values. These values are initialized to their zero values allowing you to return them before any explicit use or assignment.</fr:p><fr:pre><![CDATA[func divAndRemainder(num, denom int) (result int, remainder int, err error) {
    if denom == 0 {
        err = errors.New("cannot divide by zero")
        return result, remainder, err
    }
    result, remainder = num / denom, num % denom
    return result, remainder, err
}]]></fr:pre></fr:mainmatter><fr:backmatter /></fr:tree></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>287</fr:anchor><fr:addr
type="user">go-00sp</fr:addr><fr:route>go-00sp.xml</fr:route><fr:title
text="Closures">Closures</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>These are functions defined _within_ a function, and are able to access and modify variables declared in the outer function. Closures allow you to pass fome function state to another function. These can also be returned from a function.</fr:p><fr:pre><![CDATA[package main

import "fmt"

func main() {
    a := 20
    f := func() {
        fmt.Println(a)
        a = 30
    }
    f()
    fmt.Println(a)
}]]></fr:pre><fr:p>Anonymous function `f` can read and write `a` even though `a` is not passed in to the function. Using `:=` instead of `=` inside the closure creates a new `a` that ceases to exist when the closure exits.</fr:p><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>288</fr:anchor><fr:addr
type="user">go-00sq</fr:addr><fr:route>go-00sq.xml</fr:route><fr:title
text="Why use closures?">Why use closures?</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:ul><fr:li>Limit function scope</fr:li>
<fr:p>If a function is going to be called from only one other function, but it's called multiple times, you can use an inner function to "hide" the called function. This reduces the number of declarations at a package level, making it easier to find an unused name.</fr:p>
<fr:li>Removing logic repetetion</fr:li>
<fr:p>Given a piece of logic that is repeated multiple times within a function, a closure can be used to remove that repetition.</fr:p>
<fr:li>Passing to funcs/returning from funcs</fr:li>
<fr:p>These become really interesting, allowing you to take variables within your function and use those variables <fr:em>outside</fr:em> of the function</fr:p></fr:ul></fr:mainmatter><fr:backmatter /></fr:tree></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>289</fr:anchor><fr:addr
type="user">go-00sv</fr:addr><fr:route>go-00sv.xml</fr:route><fr:title
text="Pointers">Pointers</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Standard address (`&amp;`) and indirection/dereferencing (`*`) operators. Pointer tricks such as _pointer arithmetic_ that you can do in C are not allowed in go.</fr:p><fr:p>Before dereferencing a pointer, you must make sure it is non-nil, otherwise the program will panic if you attempt to dereference a `nil` pointer:</fr:p><fr:pre><![CDATA[var * int
fmt.Println(x == nil)			// prints true
fmt.Println(*x)					// panics]]></fr:pre><fr:p>The pointer type can be based on any type, and the built in function `new` creates a pointer variable which returns a pointer to a zero-value instance of the type.</fr:p><fr:pre><![CDATA[var x = new(int)
fmt.Println(x == nil)			// prints false
fmt.Println(*x)					// prints 0]]></fr:pre><fr:p>However, the `new` function is rarely used.</fr:p><fr:p>For structs use `&amp;` before a struct literal to create a pointer instance. When you need a pointer to a primitive type, declare a variable and then point to it.</fr:p></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>290</fr:anchor><fr:addr
type="user">go-00sw</fr:addr><fr:route>go-00sw.xml</fr:route><fr:title
text="Pointers of constants / literals">Pointers of constants / literals</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Constant literals cannot use `&amp;` because they don't have a memory address, e.g.</fr:p><fr:pre><![CDATA[type person struct {
    FirstName string
    MiddleName *string
    LastName string
}

p := person {
        FirstName: "Pat",
        MiddleName: "Perry", // This line will not compile
        LastName: "Peterson",
    }]]></fr:pre><fr:p>There are two ways around the problem. The first is to introduce a variable to hold the constant. The second is to write a generic helper function that takes a parameter of any type and returns a pointer to that type:</fr:p><fr:pre><![CDATA[func makePointer[T any](t T) *T {
  return &t
}]]></fr:pre><fr:p>which allows one to write the previous code as</fr:p><fr:pre><![CDATA[p := person {
        FirstName: "Pat",
        MiddleName: makePointer("Perry"),
        LastName: "Peterson",
    }]]></fr:pre><fr:p>**NOTE**: The only time you should use pointer parameters to modify a variable is when the function expects an interface, e.g. JSON.</fr:p></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>291</fr:anchor><fr:addr
type="user">go-00sx</fr:addr><fr:route>go-00sx.xml</fr:route><fr:title
text="Difference between maps and slices">Difference between maps and slices</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Within the go runtime, a map is implemented as a pointer to a struct, so passing a map to a function means that you are copying a pointer. Thus changes made to a map within the functions are reflected in the original.</fr:p><fr:p>**NOTE**: maps for input parameters or return values should be carefully considered. On an API design level, they are a bad choice because they say nothing about the values contained within. In general one should prefer a struct for these cases.</fr:p><fr:p>A slice is more complicated. Any modification to a slices contents within a function is reflected in the original, but using append to change the length of the array is not, even if the slice has a capacity greater than its length. This is due to slice being implemented a struct with three fields:</fr:p><fr:ul><fr:li><fr:code>int</fr:code> for length</fr:li>
<fr:li><fr:code>int</fr:code> for capcity</fr:li>
<fr:li>a pointer to a block of memory</fr:li></fr:ul></fr:mainmatter><fr:backmatter /></fr:tree></fr:mainmatter><fr:backmatter /></fr:tree></fr:mainmatter><fr:backmatter /></fr:tree></fr:backmatter></fr:tree>