A package can be imported more than once in a source file.

A Go source file can imports the same package multiple times, but the import names must be different. These same-package imports reference the same package instance. For example: package main import "fmt" import "io" import inout "io" func main() { fmt.Println(&inout.EOF == &io.EOF) // true } For example:

The comment // import "x.y.z/mypkg" following package mypkg is meaningful for the standard Go compiler.

"x.y.z/mypkg" . package mypkg // import "x.y.z/mypkg" ... For example, when the source files importing this package are compiled by the standard Go compiler, the import path of the following package must be However, since Go Toolchain 1.11, the restriction doesn't apply for modules based and vendored packages.

The default branch in switch and select blocks can be put before all case branches, after all case branches, or between case branches.

switch n := rand.Intn(3); n { case 0: fmt.Println("n == 0") case 1: fmt.Println("n == 1") default: fmt.Println("n == 2") } switch n := rand.Intn(3); n { default: fmt.Println("n == 2") case 0: fmt.Println("n == 0") case 1: fmt.Println("n == 1") } switch n := rand.Intn(3); n { case 0: fmt.Println("n == 0") default: fmt.Println("n == 2") case 1: fmt.Println("n == 1") } var x, y chan int select { case For example:

The numeric constant case expressions in a switch block can't be duplicate, but boolean ones can.

package main func main() { switch 123 { case 123: case 123: // error: duplicate case } } But the following program compiles okay. package main func main() { switch false { case false: case false: } } For example, the following program fails to compile.But the following program compiles okay. For reasons, please read this issue. The behavior is compiler dependent. In fact, the standard Go compiler also doesn't allow duplicate string case expressions, but gccgo allows.

The switch expressions in switch block are always evaluated to typed values.

123 in the following switch block is viewed as a value of int instead of an untyped integer. So the following program fails to compile. package main func main() { switch 123 { case int64(123): // error: mismatched types case uint32(789): // error: mismatched types } } For example, the switch expressionin the followingblock is viewed as a value ofinstead of an untyped integer. So the following program fails to compile.

The default switch expression of a switch block is a typed value true of the predeclared type bool .

true . package main import "fmt" func main() { switch { // <=> switch true { case true: fmt.Println("true") case false: fmt.Println("false") } } For example, the following program will print

Sometimes, the open brace { of an explicit code block can be put on the next line.

package main func main() { var i = 0 Outer: for { // okay on the next line switch { // okay on the next line case i == 5: break Outer default: i++ } } } For example: What result will the following program print? true or false ? The answer is true . Please read package main import "fmt" func False() bool { return false } func main() { switch False() { case true: fmt.Println("true") case false: fmt.Println("false") } } What result will the following program print?or? The answer is. Please read line break rules in Go for reasons.

Some case branch blocks must be explicit.

func demo(n, m int) (r int) { switch n { case 123: if m > 0 { goto End } r++ End: // syntax error: missing statement after label default: r = 1 } return } To make it compile okay, the case branch code block should be explicit: func demo(n, m int) (r int) { switch n { case 123: { if m > 0 { goto End } r++ End: } default: r = 1 } return } Alternatively, we can let a semicolon follow the label declaration End: : func demo(n, m int) (r int) { switch n { case 123: if m > 0 { goto End } r++ End:; default: r = 1 } return } For example, the following program fails to compile.To make it compile okay, thebranch code block should be explicit:Alternatively, we can let a semicolon follow the label declaration Please read line break rules in Go for reasons.

A nested deferred function calls can modify return result values of its innermost nesting function.

package main import "fmt" func F() (r int) { defer func() { r = 789 }() return 123 // <=> r = 123; return } func main() { fmt.Println(F()) // 789 } For example:

Some recover calls may be no-ops.

We should call the recover function at the right places. Please read the right places to call the built-in recover function for details.

Exit a program with a os.Exit function call and exit a goroutine with a runtime.Goexit function call.

We can exit a program from any function by calling the os.Exit function. An os.Exit function call takes an int code as argument and returns the code to operating system. An example: // exit-example.go package main import "os" import "time" func main() { go func() { time.Sleep(time.Second) os.Exit(1) }() select{} } Run it: $ go run a.go exit status 1 $ echo $? 1 An example:Run it: We can make a goroutine exit by calling the runtime.Goexit function. The runtime.Goexit function has no parameters. In the following example, the Java word will not be printed. package main import "fmt" import "runtime" func main() { c := make(chan int) go func() { defer func() {c In the following example, theword will not be printed.

The precedence of the increment operator ++ and the decrement -- is lower than the dereference operator * and the address-taken operator & , which are lower than the property selection operator . in selectors.

package main import "fmt" type T struct { x int y *int } func main() { var t T p := &t.x // <=> p := &(t.x) fmt.Printf("%T

", p) // *int *p++ // <=> (*p)++ *p-- // <=> (*p)-- t.y = p a := *t.y // <=> *(t.y) fmt.Printf("%T

", a) // int } For example:

The type deduction rule for the left untyped operand of a bit-shift operation depends on whether or not the right operand is a constant.

package main func main() { } const M = 2 // Compiles okay. 1.0 is deduced as an int value. var _ = 1.0 << M var N = 2 // Fails to compile. 1.0 is deduced as a float64 value. var _ = 1.0 << N Please read this article for reasons.

Values of two pointer types with different underlying types can be converted to each other if the base types of their underlying types share the same underlying type.

package main type MyInt int64 type Ta *int64 type Tb *MyInt func main() { var a Ta var b Tb // Direct conversion is not allowed. //a = Ta(b) // error // But indirect conversion is possible. y := (*MyInt)(b) x := (*int64)(y) a = x // <=> the next line a = (*int64)(y) // <=> the next line a = (*int64)((*MyInt)(b)) _ = a } An example:

Addresses of different zero-sized values may be equal, or not.

package main import "fmt" func main() { a := struct{}{} b := struct{}{} x := struct{}{} y := struct{}{} m := [10]struct{}{} n := [10]struct{}{} o := [10]struct{}{} p := [10]struct{}{} fmt.Println(&x, &y, &o, &p) // For the standard Go compiler (1.15), // x, y, o and p escape to heap, but // a, b, m and n are allocated on stack. fmt.Println(&a == &b) // false fmt.Println(&x == &y) // true fmt.Println(&a == &x) // false fmt.Println(&m == &n) // false fmt.Println(&o == &p) // true fmt.Println(&n == &p) // false } Whether or not the addresses of two zero-sized values are equal is compiler and compiler version dependent. The outputs indicated in the above code are for the standard Go compiler 1.15.

The base type of a pointer type may be the pointer type itself.

package main func main() { type P *P var p P p = &p p = **************p } An example: Similarly, the element type of a slice type can be the slice type itself,

the element type of a map type can be the map type itself,

the element type of a channel type can be the channel type itself,

and the argument and result types of a function type can be the function type itself. package main func main() { type S []S type M map[string]M type C chan C type F func(F) F s := S{0:nil} s[0] = s m := M{"Go": nil} m["Go"] = m c := make(C, 3) c Similarly,

A detail about selector shorthands.

For a pointer value, which type is either defined or not, if the base type of its (pointer) type is a struct type, then we can select the fields of the struct value referenced by the pointer value through the pointer value. However, if the type of the pointer value is a defined type, then we can't select the methods of the struct value referenced by the pointer value through the pointer value. package main type T struct { x int } func (T) m(){} // T has one method. type P *T // a defined one-level pointer type. type PP *P // a defined two-level pointer type. func main() { var t T var tp = &t var tpp = &tp var p P = tp var pp PP = &p tp.x = 12 // okay p.x = 34 // okay pp.x = 56 // error: type PP has no field or method x tpp.x = 78 // error: type **T has no field or method x tp.m() // okay. Type *T also has a "m" method. p.m() // error: type P has no field or method m pp.m() // error: type PP has no field or method m tpp.m() // error: type **T has no field or method m }

Sometimes, nested composite literals can be simplified.

Please read nested composite literals can be simplified for details.

In some scenarios, it is ok to use array pointers as arrays.

Please read use array pointers as arrays for details.

Retrieving elements from nil maps will not panic. The result is a zero element value.

Foo1 and the Foo2 functions are equivalent, but the function Foo2 is much tidier than the function Foo1 . func Foo1(m map[string]int) int { if m != nil { return m["foo"] } return 0 } func Foo2(m map[string]int) int { return m["foo"] } For example, theand thefunctions are equivalent, but the functionis much tidier than the function

Deleting an entry from a nil map will not panic. It is a no-op.

package main func main() { var m map[string]int // nil delete(m, "foo") } For example, the following program will not panic.

The result slice of an append function call may share some elements with the original slice, or not.

Please read append and delete container elements for details.

The length of a subslice may be larger than the base slice the subslice derives from.

package main import "fmt" func main() { s := make([]int, 3, 9) fmt.Println(len(s)) // 3 s2 := s[2:7] fmt.Println(len(s2)) // 5 } For example, Please read derive slices from arrays and slices for details.

Deriving a subslice from a nil slice is ok if all the indexes used in the subslice expression are zero. The result subslice is also a nil slice.

package main import "fmt" func main() { var x []int // nil a := x[:] b := x[0:0] c := x[:0:0] // Print three "true". fmt.Println(a == nil, b == nil, c == nil) } For example, the following program will not panic at run time. Please read derive slices from arrays and slices for details.

Ranging over a nil maps or a nil slices is ok, it is a no-op.

package main func main() { var s []int // nil for range s { } var m map[string]int // nil for range m { } } For example, the following program compiles okay.

Range over a nil array pointer is ok if the second iteration variable is ignored or omitted.

01234 . package main import "fmt" func main() { var a *[5]int // nil for i, _ := range a { fmt.Print(i) } } For example, the following program will print

The length and capacity of a slice can be modified separately.

We can modify the length and capacity of a slice separately through the reflection way. Please read modify the length and capacity properties of a slice individually for details.

The indexes in slice and array composite literals must be constants and non-negative.

var k = 1 // error: index must be non-negative integer constant var x = [2]int{k: 1} // error: index must be non-negative integer constant var y = []int{k: 1} For example, the following code fails to compile. Note, the keys in map composite literals are not required to be constants.

The constant indexes or keys in slice/array/map composite literals can't be duplicate.

// error: duplicate index in array literal: 1 var a = []bool{0: false, 1: true, 1: true} // error: duplicate index in array literal: 0 var b = [...]string{0: "foo", 1: "bar", 0: "foo"} // error: duplicate key "foo" in map literal var c = map[string]int{"foo": 1, "foo": 2} For example, the following code fails to compile. This feature can be used to assert some conditions at compile time.

Elements of unaddressable arrays are also unaddressable, but elements of unaddressable slices are always addressable.

The reason is the elements of an array value and the array will be stored in the same memory block when the array is stored in memory. But the situation is different for slices. An example: package main func main() { // Container composite literals are unaddressable. // It is ok to take slice literal element addresses. _ = &[]int{1}[0] // ok // Cannot take addresses of array literal elements. _ = &[5]int{}[0] // error // It is ok to modify slice literal elements. []int{1,2,3}[1] = 9 // ok // Cannot modify array literal elements. [3]int{1,2,3}[1] = 9 // error } An example:

It is ok to derive subslices from unaddressable slices, but not ok from unaddressable arrays.

The reason is the same as the last detail. An example: package main func main() { // Map elements are unaddressable in Go. // The following lines compile okay. Deriving // slices from unaddressable slices is allowed. _ = []int{6, 7, 8, 9}[1:3] var ms = map[string][]int{"abc": {0, 1, 2, 3}} _ = ms["abc"][1:3] // The following lines fail to compile. Deriving // slices from unaddressable arrays is not allowed. /* _ = [...]int{6, 7, 8, 9}[1:3] // error var ma = map[string][4]int{"abc": {0, 1, 2, 3}} _ = ma["abc"][1:3] // error */ } An example:

Putting entries with NaN as keys to a map is like putting the entries in a black hole.

NaN != NaN , which is another detail will be described NaN as keys can only be found out in a for-range loop, Since Go 1.12, the elements with NaN as keys can also be printed out by fmt.Print alike functions. package main import "fmt" import "math" func main() { var a = math.NaN() fmt.Println(a) // NaN var m = map[float64]int{} m[a] = 123 v, present := m[a] fmt.Println(v, present) // 0 false m[a] = 789 v, present = m[a] fmt.Println(v, present) // 0 false fmt.Println(m) // map[NaN:789 NaN:123] delete(m, a) // no-op fmt.Println(m) // map[NaN:789 NaN:123] for k, v := range m { fmt.Println(k, v) } // the above loop outputs: // NaN 123 // NaN 789 } This reason is, which is another detail will be described below . Before Go 1.12, the elements withas keys can only be found out in aloop, Since Go 1.12, the elements withas keys can also be printed out byalike functions. Please note, before Go 1.12, the two fmt.Println(m) calls both printed map[NaN:<nil> NaN:<nil>] .

The capacity of the result slice of a conversion from a string to byte/rune slice may be larger than the length of the result slice.

We should not assume the length and the capacity of the result slice are always equal. In the following example, if the last fmt.Println line is removed, the outputs of the two lines before it print the same value 32 , otherwise, one print 32 and one print 8 (for the standard Go compiler 1.15). package main import "fmt" func main() { s := "a" x := []byte(s) // len(s) == 1 fmt.Println(cap([]byte(s))) // 32 fmt.Println(cap(x)) // 8 fmt.Println(x) } In the following example, if the lastline is removed, the outputs of the two lines before it print the same value, otherwise, one printand one print(for the standard Go compiler 1.15). Some buggy code will be written if we assume the length and the capacity of the result slice are always equal.

For a slice s , the loop for i = range s {...} is not equivalent to the loop for i = 0; i < len(s); i++ {...} .

i may be different for the two loops. package main import "fmt" var i int func fa(s []int, n int) int { i = n for i = 0; i < len(s); i++ {} return i } func fb(s []int, n int) int { i = n for i = range s {} return i } func main() { s := []int{2, 3, 5, 7, 11, 13} fmt.Println(fa(s, -1), fb(s, -1)) // 6 5 s = nil fmt.Println(fa(s, -1), fb(s, -1)) // 0 -1 } The respective final values of the iteration variablemay be different for the two loops.

A multi-result function call can't mix with other expressions when the call is used as the sources in an assignment or the arguments of another function call.

Please read use function calls as expressions for details.

Some function calls are evaluated at compile time.

Please read some function calls are evaluated at compile time for details.

Each method corresponds to an implicit function.

Please read each Method Corresponds to an Implicit Function for details.

Comparing two interface values with the same dynamic incomparable type produces a panic.

package main func main() { var x interface{} = []int{} _ = x == x // panic } For example:

Type assertions can be used to convert a value of an interface type to another interface type, even if the former interface type doesn't implement the latter one.

package main type Foo interface { foo() } type T int func (T) foo() {} func main() { var x interface{} = T(123) // The following two lines fails to compile, for the // same reason: interface{} does not implement Foo. /* var _ Foo = x // error var _ = Foo(x) // error */ // But the following line compiles and runs okay. var _ = x.(Foo) // okay } For example:

Whether or not the second optional result of a type assertion is present will affect the behavior of the type assertion.

package main func main() { var x interface{} = true // Assertion fails, but doesn't cause a panic. _, _ = x.(int) // Assertion fails, which causes a panic. _ = x.(int) } If the second optional result presents in a failed type assertion, the type assertion will not produce a panic. Otherwise, a panic will occur. For example:

About the impossible to-interface assertions which can be detected at compile time.

package main type Ia interface { m() } type Ib interface { m() int } type T struct{} func (T) m() {} func main() { var x Ia = T{} _ = x.(Ib) // panic: main.T is not main.Ib } At compile time, some to-interface assertions can be deducted as impossible to succeed. For example, the assertion shown in the following code: Such assertions will not make code compilations fail (but the program will panic at run time). Since Go Toolchain 1.15, the go vet command warns on such assertions.

Two error values returned by two errors.New calls with the same argument are not equal.

errors.New function will copy the input string argument and use a pointer to the copied string as the dynamic value of the returned error value. Two different calls will produce two different pointers. package main import "fmt" import "errors" func main() { notfound := "not found" a, b := errors.New(notfound), errors.New(notfound) fmt.Println(a == b) // false } The reason is thefunction will copy the input string argument and use a pointer to the copied string as the dynamic value of the returnedvalue. Two different calls will produce two different pointers.

Receive-only channels can't be closed.

package main func main() { } func foo(c For example, the following code fails to compile.

Sending a value to a closed channel is viewed as a non-blocking operation, and this operation causes a panic.

case branch gets selected, it will produce a panic at run time. package main func main() { var c = make(chan bool) close(c) select { case For example, in the following program, when the secondbranch gets selected, it will produce a panic at run time.

Types can be declared within function bodies.

package main func main() { type T struct{} type S = []int } Types can be declared in function bodies. For example,

For the standard compiler, zero-sized fields in a struct may be treated as one-byte-sized value.

Please read this FAQ item for details.

NaN != NaN, Inf == Inf.

package main import "fmt" import "math" func main() { var a = math.Sqrt(-1.0) fmt.Println(a) // NaN fmt.Println(a == a) // false var x = 0.0 var y = 1.0 / x var z = 2.0 * y fmt.Println(y, z, y == z) // +Inf +Inf true } This follows IEEE-754 standard and is consistent with most other programming languages:

Non-exported method names and struct field names from different packages are viewed as different names.

foo : package foo type I = interface { about() string } type S struct { a string } func (s S) about() string { return s.a } and the following types are declared in package bar : package bar type I = interface { about() string } type S struct { a string } func (s S) about() string { return s.a } then, values of the two respective types S from the two packages can't be converted to each other.

from the two packages can't be converted to each other. the two respective interface types S from the two packages denote two distinct method sets.

from the two packages denote two distinct method sets. type foo.S doesn't implement the interface type bar.I .

doesn't implement the interface type . type bar.S doesn't implement the interface type foo.I . package main import "包2/foo" import "包2/bar" func main() { var x foo.S var y bar.S var _ foo.I = x var _ bar.I = y // The following lines fail to compile. x = foo.S(y) y = bar.S(x) var _ foo.I = y var _ bar.I = x } For example, if the following types are declared in packageand the following types are declared in packagethen,

In struct value comparisons, blank fields will be ignored.

_ . The following program will print true . package main import "fmt" type T struct { _ int _ bool } func main() { var t1 = T{123, true} var t2 = T{789, false} fmt.Println(t1 == t2) // true } Blank fields are those fields whose name are the blank identifier. The following program will print

Parentheses are required in several rare scenarios to make code compile okay.

package main type T struct{x, y int} func main() { // Each of the following three lines makes code // fail to compile. Some "{}"s confuse compilers. /* if T{} == T{123, 789} {} if T{} == (T{123, 789}) {} if (T{}) == T{123, 789} {} var _ = func()(nil) // nil is viewed as a type */ // We must add parentheses like the following // two lines to make code compile okay. if (T{} == T{123, 789}) {} if (T{}) == (T{123, 789}) {} var _ = (func())(nil) // nil is viewed as a value } For example:

Stack overflow is not panic.

package main func f() { f() } func main() { defer func() { recover() // helpless to avoid program crashing }() f() } the running result: runtime: goroutine stack exceeds 1000000000-byte limit fatal error: stack overflow runtime stack: ... For the current main stream Go compilers, stack overflows are fatal errors. Once a stack overflow happens, the whole program will crash without recovery ways.the running result: About more crash cases, please read this wiki article.

Some expression evaluation orders in Go are compiler implementation dependent.

Please read expression evaluation orders in Go for details.

The results of reflect.DeepEqual(x, y) and x == y may be different.

The function call reflect.DeepEqual(x, y) will always return false if the types of its two arguments are different, whereas x == y may return true even if the types of the two operands are different. The second difference is a DeepEqual call with two pointer argument values of the same type returns whether or not the two respective values referenced by the two pointers are deep equal. So the call might return true even if the two pointers are not equal. The third difference is the result of a DeepEqual call may be not correct if the compared two arguments are in the same cyclic reference chain. The fourth difference is, the function call reflect.DeepEqual(x, y) is not expected to panic generally, whereas x == y will panic if the two operands are both interface values and their dynamic types are identical and incomparable. An example showing these differences: package main import ( "fmt" "reflect" ) func main() { type Book struct {page int} x := struct {page int}{123} y := Book{123} fmt.Println(reflect.DeepEqual(x, y)) // false fmt.Println(x == y) // true z := Book{123} fmt.Println(reflect.DeepEqual(&z, &y)) // true fmt.Println(&z == &y) // false type T struct{p *T} t := &T{&T{nil}} t.p.p = t // form a cyclic reference chain. fmt.Println(reflect.DeepEqual(t, t.p)) // true fmt.Println(t == t.p) // false var f1, f2 func() = nil, func(){} fmt.Println(reflect.DeepEqual(f1, f1)) // true fmt.Println(reflect.DeepEqual(f2, f2)) // false var a, b interface{} = []int{1, 2}, []int{1, 2} fmt.Println(reflect.DeepEqual(a, b)) // true fmt.Println(a == b) // panic } An example showing these differences: Note, if the two arguments of a DeepEqual call are both function values, then the call returns true only if the two function arguments are both nil and their types are identical. It is similar to compare container values whose elements contain function values or compare struct values whose fields contain function values. But please also note that the result of comparing two slices (of the same type) is always true if the two slices exactly share the same elements (in other words, they have the same length and each pair of their corresponding elements have the same address). An example: package main import ( "fmt" "reflect" ) func main() { a := [1]func(){func(){}} b := a fmt.Println(reflect.DeepEqual(a, a)) // false fmt.Println(reflect.DeepEqual(a[:], a[:])) // true fmt.Println(reflect.DeepEqual(a[:], b[:])) // false a[0] = nil fmt.Println(reflect.DeepEqual(a, a)) // true } Note, if the two arguments of acall are both function values, then the call returnsonly if the two function arguments are both nil and their types are identical. It is similar to compare container values whose elements contain function values or compare struct values whose fields contain function values. But please also note that the result of comparing two slices (of the same type) is alwaysif the two slices exactly share the same elements (in other words, they have the same length and each pair of their corresponding elements have the same address). An example:

The reflect.Value.Bytes() method returns a []byte value, which element type, byte , might be not the same as the Go slice value represented by the receiver parameter.

Assume the underlying type of a defined type MyByte is the predeclared type byte , we know that Go type system forbids the conversions between []MyByte and []byte values. However, it looks the implementation of the method Bytes of the reflect.Value type partially violates this restriction unintentionally, by allowing converting a []MyByte value to []byte . Example: package main import "bytes" import "fmt" import "reflect" type MyByte byte func main() { var mybs = []MyByte{'a', 'b', 'c'} var bs []byte // bs = []byte(mybs) // this line fails to compile v := reflect.ValueOf(mybs) bs = v.Bytes() // okay. Violating Go type system. fmt.Println(bytes.HasPrefix(bs, []byte{'a', 'b'})) // true bs[1], bs[2] = 'r', 't' fmt.Printf("%s

", mybs) // art } Example: But it looks the violation is not harmful. On the contrary, it makes some benefits. For example, with this violation, we can use the functions in the bytes standard package for the []MyByte values. Note, the reflect.Value.Bytes() method might be removed later.

We should use os.IsNotExist(err) instead of err == os.ErrNotExist to check whether or not a file exists.

err == os.ErrNotExist may miss errors. package main import ( "fmt" "os" ) func main() { _, err := os.Stat("a-nonexistent-file.abcxyz") fmt.Println(os.IsNotExist(err)) // true fmt.Println(err == os.ErrNotExist) // false } Usingmay miss errors. For projects only supporting Go 1.13+, errors.Is(err, os.ErrNotExist) is package main import ( "errors" "fmt" "os" ) func main() { _, err := os.Stat("a-nonexistent-file.abcxyz") fmt.Println(errors.Is(err, os.ErrNotExist)) // true } For projects only supporting Go 1.13+,is more recommended to be used to check whether or not a file exists.

The flag standard package treats boolean command flags differently than integer and string flags.

-flag , for boolean flags only. -flag=x , for any flag. -flag x , for non-boolean flags only. There are three forms to pass flag options. And please note that, a boolean flag with the first form is viewed as the last flag, all items following it are viewed as arguments. package main import "fmt" import "flag" var b = flag.Bool("b", true, "a boolean flag") var i = flag.Int("i", 123, "an integer flag") var s = flag.String("s", "hi", "a string flag") func main() { flag.Parse() fmt.Print("b=", *b, ", i=", *i, ", s=", *s, "

") fmt.Println("arguments:", flag.Args()) } If we run the following program with the below shown flags and arguments ./exampleProgram -b false -i 789 -s bye arg0 arg1 the output will be b=true, i=123, s=hi arguments: [false -i 789 -s bye arg0 arg1] If we run the following program with the below shown flags and argumentsthe output will be This output is obviously not what we expect. We should pass the flags and arguments like ./exampleProgram -b=false -i 789 -s bye arg0 arg1 or ./exampleProgram -i 789 -s bye -b arg0 arg1 to get the output we expect: b=true, i=789, s=bye arguments: [arg0 arg1] We should pass the flags and arguments likeorto get the output we expect:

[Sp|Fp|P]rintf functions support positional arguments.