GO 基础语法(2)——指针结构体集合并发反射

本文介绍了Go语言的基础语法,包括指针、结构体的使用,详细阐述了range遍历map的操作,接口定义及并发概念,特别是并发中goroutine的工作原理。还提及了反射的应用,强调了Go反射中字段必须是可读写的特性,并通过示例说明了如何正确修改变量的内存值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、指针

//指针 获取对象、变量的内存地址
//取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。
//指针类型前面加上 * 号(前缀)来获取指针所指向的内容
func pointDef() {
	//定义指针变量
	var ip *int /* 指向整型*/
	//获取变量地址
	a := 1
	fmt.Println("变量的内存地址:", &a)
	//通过指针变量访问目标地址
	ip = &a
	fmt.Println("ip变量的目标指针存储地址:", ip)
	fmt.Println("ip指针所指向的内容:", *ip)

	//空指针
	var ptr *int
	if (ptr == nil) {
		fmt.Printf("ptr 为空指针,值为 : %x\n", ptr)
	}

	//向函数传递指针
	b := 2
	var x *int
	var y *int
	x = &a
	y = &b
	//传入指针 值分别为1 2
	swap(x, y)
}

//指针传入函数
func swap(x *int, y *int) {
	var temp int

	//指针传值
	temp = *x //x指针指向的值赋值给tmp
	fmt.Println("temp:", temp)
	*x = *y //y指针指向的值,赋值给x指针
	fmt.Println("*x:", *x)
	fmt.Println("x赋值给y前,y地址:", y)
	*y = temp //temp 赋值给y值
	fmt.Println("*y:", *y)

	//打印指针指向地址
	fmt.Println("x地址:", x)
	fmt.Println("y地址:", y)
}

二、结构体

//声明结构体; 等同java 对象 
type Book struct {
	title string
	author string
}

func stuctDef(){
	//实例化book
	var goBook Book
	goBook.title = "Go"
	goBook.author = "Max"
	//book属性引用
	fmt.Println(goBook.title)
}

三、range遍历

//range 数组 ,用于遍历圈定遍历范围
func rangeDef() {
	//准备一个slice数组
	nums := []int{2, 3, 4}
	sum := 0
	//利用range遍历数组进行求和;_ 表示不用关注循环的i次数
	for _, num := range nums {
		if num == 3 {
			fmt.Println("range中做判断", 3)
		}
		sum += num
	}
	fmt.Println("sum:", sum)

	//利用range 遍历map的kv
	//声明一个map
	kvs := map[string]string{"a": "apple", "b": "banana"}
	for k, v := range kvs {
		fmt.Printf("%s -> %s\n", k, v)
	}
}

四、集合 map

func mapDef() {
	//创建map
	goMap := make(map[string]string)
	goMap["key1"] = "go1"
	goMap["key2"] = "go2"
	goMap["key3"] = "go3"

	//创建map
	goMap2 := map[string]string{"1": "1", "2": "2", "3": "3"}
	for v := range goMap2 {
		fmt.Println(v)
	}

	//遍历map kv
	for name := range goMap {
		fmt.Println(name)
	}

	for k, v := range goMap {
		fmt.Println("k:", k, "v:", v)
	}

	//删除key
	delete(goMap, "key1")
	//遍历 输出key
	for key := range goMap {
		fmt.Println(key, "key is", goMap [ key ])
	}
}

五、接口定义

import "fmt"

//定义接口
type VowelsFinder interface {
	FindVowels() []rune
}

type MyString string

//实现接口
func (ms MyString) FindVowels() []rune {
	var vowels []rune
	for _, rune := range ms {
		if rune == 'a' || rune == 'e' || rune == 'i' || rune == 'o' || rune == 'u' {
			vowels = append(vowels, rune)
		}
	}
	return vowels
}

func main() {
	name := MyString("Sam Anderson") // 类型转换
	// 调用接口
	var v VowelsFinder
	v = name
	fmt.Printf("Vowels are %c", v.FindVowels())
}

六、并发

goroutine是通过Go的runtime管理的一个线程管理器,通过关键字go就启动了一个goroutine(一个线程)。

package main

import (
	"fmt"
	"runtime"
)

func say(s string) {
	for i := 0; i < 5; i++ {
		runtime.Gosched()
		fmt.Println(s)
	}
}

func main() {
	go say("hello") //开一个新的Goroutines执行
	say("world")    //当前Goroutine执行
}

可以测试把main中的go关键字去掉zaiz在执行,此时的say("hello")和say("world")则开始串行执行。证明采用go关键字,确实新起了一个线程并行打印hello world。

七、反射

熟悉java的coder,反射肯定都烂熟于心了,go的反射也同理,不过要注意,go反射的字段一定是可读写的,比如下例,拿一个4的int常量值来反射修改成8,会报错。而应该拿到x=4中x的内存地址进行修改。要修改的是变量内存指向8,而数值本身是4就是4,是不可写的。

//反射
func reflectDef() {
	x := 4
	t := reflect.TypeOf(x)
	v := reflect.ValueOf(x)

	//v.SetInt(8) //报错 反射的字段必须是可读写的

	//改写成
	p:=reflect.ValueOf(&x) //拿到x变量的内存地址
	v2:=p.Elem() //赋值给v2 再修改v2

	v2.SetInt(8)
	fmt.Println("反射获取变量类型为:",t)
	fmt.Println(v)
	fmt.Println("反射修改v的值为:",v2)
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值