Go的基本数据类型

Posted by William Basics on Tuesday, April 20, 2021

Go的基本数据类型

数字数据类型

整数

Go 支持 int8, int16, int32, int64, uint8, uint16, uint32, 以及 uint64。

一般直接用 int 和 unint 。

另外,byte 是 uint8 的别名。

浮点数

Go 支持 float32 和 float64 。前者保证小数点后6位,后者保证15位的精度。

复数

Go 支持 complex64 和 complex128 。前者用两个 float32 来分别表示实数和虚数部分。后者用两个 float64 来分别表示实数和虚数部分。

示例代码

package main 
 
import ( 
    "fmt" 
) 
 
func main() { 
    c1 := 12 + 1i 
    c2 := complex(5, 7) 
    fmt.Printf("Type of c1: %T\n", c1) 
    fmt.Printf("Type of c2: %T\n", c2) 
 
    var c3 complex64 = complex64(c1 + c2) 
    fmt.Println("c3:", c3) 
    fmt.Printf("Type of c3: %T\n", c3) 
 
    cZero := c3 - c3 
    fmt.Println("cZero:", cZero) 
    
    x := 12 
    k := 5 
    fmt.Println(x) 
    fmt.Printf("Type of x: %T\n", x) 
 
    div := x / k 
    fmt.Println("div", div) 
    var m, n float64 
    m = 1.223 
    fmt.Println("m, n:", m, n) 
 
    y := 4 / 2.3 
    fmt.Println("y:", y) 
 
    divFloat := float64(x) / float64(k) 
    fmt.Println("divFloat", divFloat) 
    fmt.Printf("Type of divFloat: %T\n", divFloat) 
} 

示例代码

package main 
 
import ( 
    "fmt" 
) 
 
func main() { 
    for i := 0; i < 100; i++ { 
        if i%20 == 0 { 
        	continue 
        } 
 
        if i == 95 { 
        	break 
        } 
 
        fmt.Print(i, " ") 
    } 
    
    fmt.Println() 
    i := 10 
    for { 
        if i < 0 { 
        	break 
        } 
        fmt.Print(i, " ") 
        i-- 
    } 
    fmt.Println() 
    
    i = 0 
    anExpression := true 
    for ok := true; ok; ok = anExpression { 
        if i > 10 { 
        	anExpression = false 
        } 
 
        fmt.Print(i, " ") 
        i++ 
    } 
    fmt.Println() 
    
    anArray := [5]int{0, 1, -1, 2, -2} 
    for i, value := range anArray { 
        fmt.Println("index:", i, "value: ", value) 
    } 
} 

字符串

和C语言不同,字符串在Go中是值类型。并且Go默认支持UTF-8。

在Go中,字符串是只读的byte slice。字符串中的元素可以是character, rune或者byte。

可以通过len()函数得到字符串的长度。

const sLiteral = "\x99\x42\x32\x55\x50\x35\x23\x50\x29\x9c" 
s2 := "€£³" 

示例代码

package main 
 
import ( 
    "fmt" 
) 

func main() { 
    const sLiteral = "\x99\x42\x32\x55\x50\x35\x23\x50\x29\x9c" 
    fmt.Println(sLiteral) 
    fmt.Printf("x: %x\n", sLiteral) 
 
    fmt.Printf("sLiteral length: %d\n", len(sLiteral)) 
    
    for i := 0; i < len(sLiteral); i++ { 
        fmt.Printf("%x ", sLiteral[i]) 
    } 
    fmt.Println() 
 
    fmt.Printf("q: %q\n", sLiteral) 
    fmt.Printf("+q: %+q\n", sLiteral) 
    fmt.Printf(" x: % x\n", sLiteral) 
 
    fmt.Printf("s: As a string: %s\n", sLiteral) 
    
    s2 := "€£³" 
    for x, y := range s2 { 
        fmt.Printf("%#U starts at byte position %d\n", y, x) 
    } 
 
    fmt.Printf("s2 length: %d\n", len(s2)) 
    
    const s3 = "ab12AB" 
    fmt.Println("s3:", s3) 
    fmt.Printf("x: % x\n", s3) 
 
    fmt.Printf("s3 length: %d\n", len(s3)) 
 
    for i := 0; i < len(s3); i++ { 
        fmt.Printf("%x ", s3[i]) 
    } 
    fmt.Println() 
} 

rune

rune是一个int32的值,它用来表示一个Unicode code point。一个Unicode code point 或者 code position 是一个值一般用来代表一个Unicode字符,也会用来提供格式信息。

rune一般用单引号括起来。

代码示例:

package main 
 
import ( 
    "fmt" 
) 

func main() { 
    const r1 = '€' 
    fmt.Println("(int32) r1:", r1) 
    fmt.Printf("(HEX) r1: %x\n", r1) 
    fmt.Printf("(as a String) r1: %s\n", r1) 
    fmt.Printf("(as a character) r1: %c\n", r1) 
    
    fmt.Println("A string is a collection of runes:", []byte("Mihalis")) 
    aString := []byte("Mihalis") 
    for x, y := range aString { 
        fmt.Println(x, y) 
        fmt.Printf("Char: %c\n", aString[x]) 
    } 
    fmt.Printf("%s\n", aString) 
} 

unicode

unicode包中有一个函数 unicode.IsPrint() 可以用来识别一个字符串中指定部分中的rune是否可打印。

package main 
 
import ( 
    "fmt" 
    "unicode" 
) 
 
func main() { 
    const sL = "\x99\x00ab\x50\x00\x23\x50\x29\x9c" 
    for i := 0; i < len(sL); i++ { 
        if unicode.IsPrint(rune(sL[i])) { 
            fmt.Printf("%c\n", sL[i]) 
        } else { 
            fmt.Println("Not printable!") 
        } 
    } 
} 

strings

strings 包是Go标准库中用来处理UTF-8字符串的。

package main 
 
import ( 
    "fmt" 
    s "strings" //创建一个包的别名
    "unicode" 
) 
 
var f = fmt.Printf // 创建一个函数别名

func main() { 
    upper := s.ToUpper("Hello there!") 
    f("To Upper: %s\n", upper) 
    f("To Lower: %s\n", s.ToLower("Hello THERE")) 
    f("%s\n", s.Title("tHis wiLL be A title!")) 
    f("EqualFold: %v\n", s.EqualFold("Mihalis", "MIHAlis")) 
    f("EqualFold: %v\n", s.EqualFold("Mihalis", "MIHAli")) 
    f("Prefix: %v\n", s.HasPrefix("Mihalis", "Mi")) 
    f("Prefix: %v\n", s.HasPrefix("Mihalis", "mi")) 
    f("Suffix: %v\n", s.HasSuffix("Mihalis", "is")) 
    f("Suffix: %v\n", s.HasSuffix("Mihalis", "IS")) 
 
    f("Index: %v\n", s.Index("Mihalis", "ha")) 
    f("Index: %v\n", s.Index("Mihalis", "Ha")) 
    f("Count: %v\n", s.Count("Mihalis", "i")) 
    f("Count: %v\n", s.Count("Mihalis", "I")) 
    f("Repeat: %s\n", s.Repeat("ab", 5)) 
 
    f("TrimSpace: %s\n", s.TrimSpace(" \tThis is a line. \n")) 
    f("TrimLeft: %s", s.TrimLeft(" \tThis is a\t line. \n", "\n\t  "))       
    f("TrimRight: %s\n", s.TrimRight(" \tThis is a\t line. \n",  "\n\t "))
    
    f("Compare: %v\n", s.Compare("Mihalis", "MIHALIS")) 
    f("Compare: %v\n", s.Compare("Mihalis", "Mihalis")) 
    f("Compare: %v\n", s.Compare("MIHALIS", "MIHalis")) 
 
    f("Fields: %v\n", s.Fields("This is a string!")) 
    f("Fields: %v\n", s.Fields("Thisis\na\tstring!")) 
 
    f("%s\n", s.Split("abcd efg", "")) 
    
    f("%s\n", s.Replace("abcd efg", "", "_", -1)) 
    f("%s\n", s.Replace("abcd efg", "", "_", 4)) 
    f("%s\n", s.Replace("abcd efg", "", "_", 2)) 
 
    lines := []string{"Line 1", "Line 2", "Line 3"} 
    f("Join: %s\n", s.Join(lines, "+++")) 
 
    f("SplitAfter: %s\n", s.SplitAfter("123++432++", "++")) 
 
    trimFunction := func(c rune) bool { 
        return !unicode.IsLetter(c) 
    } 
    f("TrimFunc: %s\n", s.TrimFunc("123 abc ABC \t .",  trimFunction)) 
} 

数组

示例代码

anArray := [4]int{1, 2, 4, -4}

可以用 len() 函数来获取数组大小。

len(anArray)

数组元素索引从0开始,有效范围是 0 ~ len(anArray) - 1 。

Go 的数组一旦定义,大小就是固定了。将数组作为参数传递给函数时,是传递的数组的拷贝,所以对于比较大的数组,将会造成性能上的损失。

因此,在Go 编程中,数组常常被slice所替换。

多维数组

twoD := [4][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12},  {13, 14, 15, 16}} 
threeD := [2][2][2]int{{{1, 0}, {-2, 4}}, {{5, -1}, {7, 0}}} 

代码示例

package main 
 
import ( 
    "fmt" 
) 
 
func main() { 
    anArray := [4]int{1, 2, 4, -4} 
    twoD := [4][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}} 
    threeD := [2][2][2]int{{{1, 0}, {-2, 4}}, {{5, -1}, {7, 0}}} 
    fmt.Println("The length of", anArray, "is", len(anArray)) 
    fmt.Println("The first element of", twoD, "is", twoD[0][0]) 
    fmt.Println("The length of", threeD, "is", len(threeD)) 
 
    for i := 0; i < len(threeD); i++ { 
        v := threeD[i] 
        for j := 0; j < len(v); j++ { 
            m := v[j] 
            for k := 0; k < len(m); k++ { 
                fmt.Print(m[k], " ") 
            } 
        } 
        fmt.Println() 
    } 
    for _, v := range threeD { // '_' 是占位符
        for _, m := range v { 
            for _, s := range m { 
                fmt.Print(s, " ") 
            } 
        } 
        fmt.Println() 
    } 
} 

slice

在Go 编程中,除了个别场景会用到数组以外,一般都用slice。就想在C++中,我们一般都用vector一样。并且和C++的vector一样,slice的size会自动扩展。

和数组不同,slice是按引用传递给函数的。

基本操作

定义

aSliceLiteral := []int{1, 2, 3, 4, 5} 

和数组的定义类似,但是没有指定size。

用 make() 函数创建

s := make([]int, 20)

Go会自动初始化slice,将其中的元素都设为 0 ,对象的话,会设为 nil 。

清空

s := nil

添加

s = append(s, 12)

截取

用 [ : ] 来得到slice的指定连续部分

s2 := s[1:3]

这个表达式称为重分片(re-slicing),但是需要注意的是,重分片并没有做拷贝操作,对s2的修改将导致原slice的修改。

示例代码

package main 
 
import "fmt" 
 
func main() { 
 
    s1 := make([]int, 5) 
    reSlice := s1[1:3] 
    fmt.Println(s1) 
    fmt.Println(reSlice) 
 
    reSlice[0] = -100 
    reSlice[1] = 123456 
    fmt.Println(s1) 
    fmt.Println(reSlice) 
 
} 

重分片的另一个需要注意点是,子slice会导致原slice驻留内存,直到子slice被释放。比如,在当你用slice读取一个大文件,而只使用其中一小部分的时候。

len() 和 cap()

分别获取元素个数和slice的容量。

示例代码

package main 
 
import ( 
    "fmt" 
) 
 
func printSlice(x []int) { 
    for _, number := range x { 
        fmt.Print(number, " ") 
    } 
    fmt.Println() 
} 

func main() { 
    aSlice := []int{-1, 0, 4} 
    fmt.Printf("aSlice: ") 
    printSlice(aSlice) 
 
    fmt.Printf("Cap: %d, Length: %d\n", cap(aSlice), len(aSlice)) 
    aSlice = append(aSlice, -100) 
    fmt.Printf("aSlice: ") 
    printSlice(aSlice) 
    fmt.Printf("Cap: %d, Length: %d\n", cap(aSlice), len(aSlice)) 
    aSlice = append(aSlice, -2) 
    aSlice = append(aSlice, -3) 
    aSlice = append(aSlice, -4) 
    printSlice(aSlice) 
    fmt.Printf("Cap: %d, Length: %d\n", cap(aSlice), len(aSlice)) 
} 

拷贝

可以用 copy() 来创建slice的拷贝。

注意,Go自带的copy函数,只拷贝目标和源slice中最少数量的元素。也就是说,copy操作不会修改目标slice的大小。

示例代码

package main 
 
import ( 
    "fmt" 
) 
 
func main() { 
    a6 := []int{-10, 1, 2, 3, 4, 5} 
    a4 := []int{-1, -2, -3, -4} 
    fmt.Println("a6:", a6) 
    fmt.Println("a4:", a4) 
 
    copy(a6, a4) 
    fmt.Println("a6:", a6) 
    fmt.Println("a4:", a4) 
    fmt.Println() 
    
    b6 := []int{-10, 1, 2, 3, 4, 5} 
    b4 := []int{-1, -2, -3, -4} 
    fmt.Println("b6:", b6) 
    fmt.Println("b4:", b4) 
    copy(b4, b6) 
    fmt.Println("b6:", b6) 
    fmt.Println("b4:", b4) 

    fmt.Println() 
    array4 := [4]int{4, -4, 4, -4} 
    s6 := []int{1, 1, -1, -1, 5, -5} 
    copy(s6, array4[0:]) 
    fmt.Println("array4:", array4[0:]) 
    fmt.Println("s6:", s6) 
    fmt.Println() 
    
    array5 := [5]int{5, -5, 5, -5, 5} 
    s7 := []int{7, 7, -7, -7, 7, -7, 7} 
    copy(array5[0:], s7) 
    fmt.Println("array5:", array5) 
    fmt.Println("s7:", s7) 
} 

技巧:

通过[:] 将数组转成 slice。

排序

通过sort.Slice() 函数。

代码示例

package main 
 
import ( 
    "fmt" 
    "sort" 
) 
 
type aStructure struct { 
    person string 
    height int 
    weight int 
} 

func main() { 
    mySlice := make([]aStructure, 0) 
    mySlice = append(mySlice, aStructure{"Mihalis", 180, 90}) 
    mySlice = append(mySlice, aStructure{"Bill", 134, 45}) 
    mySlice = append(mySlice, aStructure{"Marietta", 155, 45}) 
    mySlice = append(mySlice, aStructure{"Epifanios", 144, 50}) 
    mySlice = append(mySlice, aStructure{"Athina", 134, 40}) 
 
    fmt.Println("0:", mySlice) 
    
    sort.Slice(mySlice, func(i, j int) bool { 
        return mySlice[i].height < mySlice[j].height 
    }) 
    fmt.Println("<:", mySlice) 
    sort.Slice(mySlice, func(i, j int) bool { 
        return mySlice[i].height > mySlice[j].height 
    }) 
    fmt.Println(">:", mySlice) 
} 

byte slice

s := make([]byte, 5)

在Go中,byte slice一般用来保存字符串。并且Go提供了方便的方法,让你在byte slice和string类型间相互转换。

byte slice主要用于文件的读写。

多维slice

s1 := make([][]int, 4)

代码示例

package main 
 
import ( 
    "fmt" 
) 
 
func main() { 
    aSlice := []int{1, 2, 3, 4, 5} 
    fmt.Println(aSlice) 
    integers := make([]int, 2) 
    fmt.Println(integers) 
    integers = nil 
    fmt.Println(integers) 
    
    anArray := [5]int{-1, -2, -3, -4, -5} 
    refAnArray := anArray[:] 
 
    fmt.Println(anArray) 
    fmt.Println(refAnArray) 
    anArray[4] = -100 
    fmt.Println(refAnArray) 
    
    s := make([]byte, 5) 
    fmt.Println(s) 
    twoD := make([][]int, 3) 
    fmt.Println(twoD) 
    fmt.Println() 
    
    for i := 0; i < len(twoD); i++ { 
        for j := 0; j < 2; j++ { 
          twoD[i] = append(twoD[i], i*j) 
        } 
    } 
    
    for _, x := range twoD { 
        for i, y := range x { 
          fmt.Println("i:", i, "value:", y) 
        } 
        fmt.Println() 
    } 
} 

合并

package main 
 
import ( 
    "fmt" 
) 
 
func main() { 
    s := []int{1, 2, 3} 
    a := [3]int{4, 5, 6} 
    
    ref := a[:] 
    fmt.Println("Existing array:\t", ref) 
    t := append(s, ref...) 
    fmt.Println("New slice:\t", t) 
    s = append(s, ref...) 
    fmt.Println("Existing slice:\t", s) 
    s = append(s, s...) 
    fmt.Println("s+s:\t\t", s) 
} 

注意ref后面的 ‘…’ ,用它来unpack前面的ref。

map

Go中的map类似于其他语言的hash table。

创建map

m = make(map[string]int) // key是string类型,value是int类型

//or

m2 := map[string]int {
    "k1": 12,
    "k2": 15,
}

访问元素

var v = m2["k1"]

删除元素

delete(m2, "k1")

遍历元素

for key, value := range m2 {
	fmt.Println(key, value)
}

示例代码

package main 
 
import ( 
    "fmt" 
) 
 
func main() { 
 
    iMap := make(map[string]int) 
    iMap["k1"] = 12 
    iMap["k2"] = 13 
    fmt.Println("iMap:", iMap) 
 
    anotherMap := map[string]int{ 
        "k1": 12, 
        "k2": 13, 
    } 
    
    fmt.Println("anotherMap:", anotherMap) 
    delete(anotherMap, "k1") 
    delete(anotherMap, "k1") 
    delete(anotherMap, "k1")   // key可以多次删除
    fmt.Println("anotherMap:", anotherMap) 
 
    _, ok := iMap["doesItExist"] // 编码技巧:判断key是否存在
    							 // 当key不存在map中时,map会返回0,因此我们无法得知key是否存在。
    if ok { 
        fmt.Println("Exists!") 
    } else { 
        fmt.Println("Does NOT exist") 
    } 
    
    for key, value := range iMap { 
        fmt.Println(key, value) 
    } 
} 

常量

和C++或者C#一样,用const关键词来修饰常量。

const PI = 3.14

// go比较特别的写法
const (
	C1 = "1000"
	C2 = "2000"
	C3 = "3000"
)

const s1 = 123
const s2 float64 = 123  // 这种写法,在语法上更严格

常量生成器 iota

iota只能用在const scope中,总是从0开始产生累加值。在下面的示例代码中有其用法的展示。

示例代码

package main 
 
import ( 
    "fmt" 
) 
 
type Digit int 
type Power2 int 
 
const PI = 3.1415926 
 
const (
    C1 = "C1C1C1" 
    C2 = "C2C2C2" 
    C3 = "C3C3C3" 
) 

func main() { 
    const s1 = 123 
    var v1 float32 = s1 * 12 
    fmt.Println(v1) 
    fmt.Println(PI) 
    
    const ( 
        Zero Digit = iota 
        One 
        Two 
        Three 
        Four 
    ) 
    fmt.Println(One) 
    fmt.Println(Two) 
    
    const ( 
        p2_0 Power2 = 1 << iota        
        _        
        p2_2        
        _        
        p2_4        
        _        
        p2_6 
    ) 
 
    fmt.Println("2^0:", p2_0) 
    fmt.Println("2^2:", p2_2) 
    fmt.Println("2^4:", p2_4) 
    fmt.Println("2^6:", p2_6) 
 
} 
    

指针

和C/C++一样,用 * 号取指针值,用 & 号取变量地址。

代码示例

package main 
 
import ( 
    "fmt" 
) 
 
func getPointer(n *int) { 
    *n = *n * *n 
 
} 
 
func returnPointer(n int) *int { 
    v := n * n 
    return &v 
} 

func main() { 
    i := -10 
    j := 25 
 
    pI := &i 
    pJ := &j 
 
    fmt.Println("pI memory:", pI) 
    fmt.Println("pJ memory:", pJ) 
    fmt.Println("pI value:", *pI) 
    fmt.Println("pJ value:", *pJ) 
    
    *pI = 123456 
    *pI-- 
    fmt.Println("i:", i) 
    
    getPointer(pJ) 
    fmt.Println("j:", j) 
    k := returnPointer(12) 
    fmt.Println(*k) 
    fmt.Println(k) 
} 

时间和日期

首先需要引入 time package。

time package中时间的最小单位是纳秒。

package main 
 
import ( 
    "fmt" 
    "time" 
) 

func main() { 
    fmt.Println("Epoch time:", time.Now().Unix()) // 返回Unix epoch时间
    t := time.Now() 
    fmt.Println(t, t.Format(time.RFC3339)) 
    fmt.Println(t.Weekday(), t.Day(), t.Month(), t.Year()) 
 
    time.Sleep(time.Second) // wait for 1 second
    t1 := time.Now() 
    fmt.Println("Time difference:", t1.Sub(t)) // time.Sub() 用来计算时间差

    formatT := t.Format("01 January 2006") 
    fmt.Println(formatT) 
    loc, _ := time.LoadLocation("Europe/Paris") 
    londonTime := t.In(loc) 
    fmt.Println("Paris:", londonTime) 
} 

解析时间和日期

用time.Parse()

package main 
 
import ( 
    "fmt" 
    "os" 
    "path/filepath" 
    "time" 
) 

func main() { 
    var myTime string 
    if len(os.Args) != 2 { 
        fmt.Printf("usage: %s string\n", filepath.Base(os.Args[0])) 
        os.Exit(1) 
    } 
 
    myTime = os.Args[1] 
    
    d, err := time.Parse("15:04", myTime) 
    if err == nil { 
        fmt.Println("Full:", d) 
        fmt.Println("Time:", d.Hour(), d.Minute()) 
    } else { 
        fmt.Println(err) 
    } 
} 
package main 
 
import ( 
    "fmt" 
    "os" 
    "path/filepath" 
    "time" 
) 
 
func main() { 
 
    var myDate string 
    if len(os.Args) != 2 { 
        fmt.Printf("usage: %s string\n",  filepath.Base(os.Args[0])) 
        return 
    } 
 
    myDate = os.Args[1] 

    d, err := time.Parse("02 January 2006", myDate) 
    if err == nil { 
        fmt.Println("Full:", d) 
        fmt.Println("Time:", d.Day(), d.Month(), d.Year()) 
    } else { 
        fmt.Println(err) 
    } 
} 

改变时间日期格式

package main 
 
import ( 
    "fmt" 
    "regexp" 
    "time" 
) 

func main() { 
 
    logs := []string{"127.0.0.1 - - [16/Nov/2017:10:49:46 +0200]  325504",          "127.0.0.1 - - [16/Nov/2017:10:16:41 +0200] \"GET /CVEN  HTTP/1.1\" 200 12531 \"-\" \"Mozilla/5.0 AppleWebKit/537.36",          "127.0.0.1 200 9412 - - [12/Nov/2017:06:26:05 +0200]  \"GET \"http://www.mtsoukalos.eu/taxonomy/term/47\" 1507", 
          "[12/Nov/2017:16:27:21 +0300]", 
          "[12/Nov/2017:20:88:21 +0200]", 
          "[12/Nov/2017:20:21 +0200]", 
    } 
    
    for _, logEntry := range logs { 
          r := regexp.MustCompile(`.*\[(\d\d\/\w+/\d\d\d\d:\d\d:\d\d:\d\d.*)\].*`) 
          if r.MatchString(logEntry) { 
               match := r.FindStringSubmatch(logEntry) 
                dt, err := time.Parse("02/Jan/2006:15:04:05 -0700", match[1]) 
                if err == nil { 
                      newFormat := dt.Format(time.RFC850) 
                      fmt.Println(newFormat) 
                } else { 
                      fmt.Println("Not a valid date time format!") 
                } 
          } else { 
               fmt.Println("Not a match!") 
          } 
    } 
} 

测量运行时间

用time.Since(start_time)

package main 
 
import ( 
    "fmt" 
    "time" 
) 
 
func main() { 
    start := time.Now() 
    time.Sleep(time.Second) 
    duration := time.Since(start) 
    fmt.Println("It took time.Sleep(1)", duration, "to finish.") 
    
    start = time.Now() 
    time.Sleep(2 * time.Second) 
    duration = time.Since(start) 
    fmt.Println("It took time.Sleep(2)", duration, "to finish.") 

    start = time.Now() 
    for i := 0; i < 200000000; i++ { 
        _ = i 
    } 
    duration = time.Since(start) 
    fmt.Println("It took the for loop", duration, "to finish.") 
 
    sum := 0 
    start = time.Now() 
    for i := 0; i < 200000000; i++ { 
        sum += i 
    } 
    duration = time.Since(start) 
    fmt.Println("It took the for loop", duration, "to finish.") 
    
}

(end.)