7.pointers

// Sample program to show the basic concept of pass by value.
package main

func main() {
	// Declare variable of type int with a value of 10.
	count := 10

	// Display the "value of" and "address of" count.
	println("count:\tValue Of[", count, "]\tAddr Of[", &count, "]")

	// Pass the "value of" the count.
	increment(count)

	println("count:\tValue Of[", count, "]\tAddr Of[", &count, "]")

}

// increment declares count as a pointer variable whose value is
// always an address and points to values of type int.
//增量声明count作为一个指针变量,其值为。
//始终是一个地址,并指向int类型的值。

//go:noinline
func increment(inc int) {

	// Increment the "value of" inc.
	inc++
	println("inc:\tValue Of[", inc, "]\tAddr Of[", &inc, "]")
}

/*
count:	Value Of[ 10 ]	Addr Of[ 0xc420045f68 ]
inc:	Value Of[ 11 ]	Addr Of[ 0xc420045f58 ]
count:	Value Of[ 10 ]	Addr Of[ 0xc420045f68 ]
*/

Sharing data I

// Sample program to show the basic concept of using a pointer
// to share data.
package main

func main() {

	// Declare variable of type int with a value of 10.
	count := 10

	// Display the "value of" and "address of" count.
	println("1.count:\tValue Of[", count, "]\t\tAddr Of[", &count, "]")

	// Pass the "address of" count.
	increment(&count)

	println("3.count:\tValue Of[", count, "]\t\tAddr Of[", &count, "]")
}

// increment declares count as a pointer variable whose value is
// always an address and points to values of type int.
//go:noinline
func increment(inc *int) {

	// Increment the "value of" count that the "pointer points to".
	*inc++
	println("2.inc:\tValue Of[", inc, "]\tAddr Of[", &inc, "]\tValue Points To[", *inc, "]")
}

/*
1.count:	Value Of[ 10 ]		Addr Of[ 0xc420045f68 ]
2.inc:	Value Of[ 0xc420045f68 ]	Addr Of[ 0xc420045f58 ]	Value Points To[ 11 ]
3.count:	Value Of[ 11 ]		Addr Of[ 0xc420045f68 ]
*/

Sharing data II

// Sample program to show the basic concept of using a pointer
// to share data.
//示例程序演示使用指针的基本概念。
//分享数据。
package main

import "fmt"

// user represents a user in the system.//用户代表系统中的用户。
type user struct {
	name   string
	email  string
	logins int
}

func main() {
	// Declare and initialize a variable named bill of type user.
	bill := user{
		name:  "Bill",
		email: "bill@ardanlabs.com",
	}

	//** We don't need to include all the fields when specifying field
	// names with a struct literal.

	// Pass the "address of" the bill value. 通过“地址”的票据价值。
	display(&bill)

	// Pass the "address of" the logins field from within the bill value.
	increment(&bill.logins)

	// Pass the "address of" the bill value.
	display(&bill)

}

// increment declares logins as a pointer variable whose value is
// always an address and points to values of type int.
func increment(logins *int) {
	*logins++
	fmt.Printf("&logins[%p] logins[%p] *logins[%d]\n", &logins, logins, *logins)
}

// display declares u as user pointer variable whose value is always an address
// and points to values of type user.
func display(u *user) {
	fmt.Printf("%p\t%+v\n", u, *u)
}

/* 
0xc42007a180	{name:Bill email:bill@ardanlabs.com logins:0}
&logins[0xc42000c030] logins[0xc42007a1a0] *logins[1]
0xc42007a180	{name:Bill email:bill@ardanlabs.com logins:1}

*/

Escape Analysis 溢出分析

//逸出分析
// Escape Analysis

// Escape Analysis Flaws:
// https://docs.google.com/document/d/1CxgUBPlx9iJzkz9JWkb6tIpTe5q32QDmz8l0BouG0Cw/view

// Sample program to teach the mechanics of escape analysis.
package main

// user represents a user in the system.
type user struct {
	name  string
	email string
}

// main is the entry point for the application.
func main() {
	u1 := createUserV1()
	u2 := createUserV2()

	println("u1", &u1, "u2", &u2)
	/*
		V1 0xc420045ef8
		V2 0xc42000a040
		u1 0xc420045f50 u2 0xc420045f48

	*/
}

// createUserV1 creates a user value and passed
// a copy back to the caller.
//go:noinline
func createUserV1() user {
	u := user{
		name:  "Bill",
		email: "bill@ardanlabs.com",
	}

	println("V1", &u)

	return u
}

// createUserV2 creates a user value and shares
// the value with the caller.
//go:noinline
func createUserV2() *user {
	u := user{
		name:  "Bill",
		email: "bill@ardanlabs.com",
	}

	println("V2", &u)

	return &u
}

/*
// See escape analysis and inling decisions.
$ go build -gcflags "-m -m"
# github.com/ardanlabs/gotraining/topics/go/language/pointers/example4
./example4.go:27: cannot inline createUserV1: marked go:noinline
./example4.go:41: cannot inline createUserV2: marked go:noinline
./example4.go:17: cannot inline main: non-leaf function
./example4.go:33: createUserV1 &u does not escape
./example4.go:49: &u escapes to heap
./example4.go:49: 	from ~r0 (return) at ./example4.go:49
./example4.go:45: moved to heap: u
./example4.go:47: createUserV2 &u does not escape
./example4.go:21: main &u1 does not escape
./example4.go:21: main &u2 does not escape
// See the intermediate assembly phase before
// generating the actual arch-specific assembly.
$ go build -gcflags -S
"".createUserV1 t=1 size=221 args=0x20 locals=0x38
	0x0000 00000 (github.com/ardanlabs/gotraining/.../example4.go:27)	TEXT	"".createUserV1(SB), $56-32
	0x0000 00000 (github.com/ardanlabs/gotraining/.../example4.go:27)	MOVQ	(TLS), CX
	0x0009 00009 (github.com/ardanlabs/gotraining/.../example4.go:27)	CMPQ	SP, 16(CX)
	0x000d 00013 (github.com/ardanlabs/gotraining/.../example4.go:27)	JLS	211
	0x0013 00019 (github.com/ardanlabs/gotraining/.../example4.go:27)	SUBQ	$56, SP
	0x0017 00023 (github.com/ardanlabs/gotraining/.../example4.go:27)	MOVQ	BP, 48(SP)
	0x001c 00028 (github.com/ardanlabs/gotraining/.../example4.go:27)	LEAQ	48(SP), BP
// See the actual machine representation by using
// the disasembler.
$ go tool objdump -s main.main example4
TEXT main.main(SB) github.com/ardanlabs/gotraining/topics/go/language/pointers/example4/example4.go
	example4.go:18	0x104bf31	e8ba000000		CALL main.createUserV1(SB)
	example4.go:18	0x104bf36	488b0424		MOVQ 0(SP), AX
	example4.go:18	0x104bf3a	488b4c2408		MOVQ 0x8(SP), CX
	example4.go:18	0x104bf3f	488b542410		MOVQ 0x10(SP), DX
	example4.go:18	0x104bf44	488b5c2418		MOVQ 0x18(SP), BX
	example4.go:18	0x104bf49	4889442428		MOVQ AX, 0x28(SP)
	example4.go:18	0x104bf4e	48894c2430		MOVQ CX, 0x30(SP)
	example4.go:18	0x104bf53	4889542438		MOVQ DX, 0x38(SP)
	example4.go:18	0x104bf58	48895c2440		MOVQ BX, 0x40(SP)
// See a list of the symbols in an artifact with
// annotations and size.
$ go tool nm example4
 104bff0 T main.createUserV1
 104c0d0 T main.createUserV2
 104c1e0 T main.init
 10b2940 B main.initdone.
 104bf10 T main.main
 106cf80 R main.statictmp_4
*/

// Sample program to show how stacks grow/change.
package main

// Number of elements to grow each stack frame.
// Run with 10 and then with 1024
const size = 1024

// main is the entry point for the application.
func main() {
	s := "HELLO"
	stackCopy(&s, 0, [size]int{})
}

// stackCopy recursively runs increasing the size
// of the stack.
func stackCopy(s *string, c int, a [size]int) {
	println(c, s, *s)

	c++
	if c == 10 {
		return
	}

	stackCopy(s, c, a)
}


/*
0 0xc420089f60 HELLO
1 0xc420089f60 HELLO
2 0xc420099f60 HELLO
3 0xc420099f60 HELLO
4 0xc420099f60 HELLO
5 0xc420099f60 HELLO
6 0xc4200b9f60 HELLO
7 0xc4200b9f60 HELLO
8 0xc4200b9f60 HELLO
9 0xc4200b9f60 HELLO
*/

练习

package main

import "fmt"

func main() {

	// Declare an integer variable with the value of 20.
	value := 20

	// Display the address of and value of the variable.
	fmt.Println("Address Of:", &value, "Value Of:", value)

	// Declare a pointer variable of type int. Assign the
	// address of the integer variable above.
	p := &value

	// Display the address of, value of and the value the pointer
	// points to.
	fmt.Println("Address Of:", &p, "Value Of:", p, "Points To:", *p)
}


/*
Address Of: 0xc4200140a0 Value Of: 20
Address Of: 0xc42000c030 Value Of: 0xc4200140a0 Points To: 20
*/
// Declare a struct type and create a value of this type. Declare a function
// that can change the value of some field in this struct type. Display the
// value before and after the call to your function.
package main

import "fmt"

// user represents a user in the system.
type user struct {
	name        string
	email       string
	accessLevel int
}

func main() {

	// Create a variable of type user and initialize each field.
	bill := user{
		name:        "Bill",
		email:       "bill@ardanlabs.com",
		accessLevel: 1,
	}

	// Display the value of the accessLevel field.
	fmt.Println("access:", bill.accessLevel)

	// Share the bill variable with the accessLevel function
	// along with a value to update the accessLevel field with.
	accessLevel(&bill, 10)

	// Display the value of the accessLevel field again.
	fmt.Println("access:", bill.accessLevel)
}

// accessLevel changes the value of the users access level.
func accessLevel(u *user, accessLevel int) {

	// Set of value of the accessLevel field to the value
	// that is passed in.
	u.accessLevel = accessLevel
}


/*
access: 1
access: 10
*/

posted on 2018-03-17 00:51  cucy_to  阅读(156)  评论(0编辑  收藏  举报

导航