风离不摆烂学习日志 Day7 Go 指针

image-20221125234042974

指针概念

指针是一个代表着某个内存地址的值。

这个内存地址往往是在内存中存住的两一个变量的值的起始位置。Go语言对指针的支持介于Java语言和C/C语言之间,它既没有像Java语言那样取消了代码对指针的直接操作的能力,也避免了C/C语言中由于对指针的滥用而造成的安全和可靠性问题。

Go语言虽然保留了指针,但与其他编程语言不同的是:

  • 默认值nil,没有NULL常量。
  • 操作符"&“取变量地址,”*"通过指针访问目标对象。
  • 不支持指针运算,不支持"->“运算符,直接用”."访问目标成员。
package main

import "fmt"

func main() {
	var a = 10
	//每个变量有2层含义,变量的内存和变量的地址
	fmt.Printf("a = %d\n", a)  //a,变量的内存,也就是存在内存当中的内容
	fmt.Printf("&a = %v\n", a) //&a,变量的地址,也就是内存所在内存当中的位置,也叫指针
}

重要 不要操作有合法指向的内存 (Java空指针)

image-20221125230935901

panic: runtime error: invalid memory address or nil pointer dereference

这类错误以后很常见 即空指针

package main

import "fmt"

func main() {
	var p *int

	*p = 666 //err,因为p没有合法指向。
	var a int
	p = &a //p指向a的指针
	*p = 666
	fmt.Println("a = ", a)

}

举个实战具体的例子

/**
  返回值类型为  *model.School
   我们 不能直接在
  err := common.DB.First(&school, "school_name = ?", schoolName).Error 会空指针异常 因为还没关联上地址

 //给 school 关联上 copySchool
	school = &copySchool
*/

func (sr SchoolRepository) SelectBySchoolName(schoolName string) (*model.School, error) {
	common.Log.Info("Db 层 取到的schoolName ", schoolName)

	//这里写查询语句
	var school *model.School

	var copySchool model.School

	//给 school 关联上 copySchool
	school = &copySchool

	//查询
	err := common.DB.First(&school, "school_name = ?", schoolName).Error
	common.Log.Info("err : ", err)

	if err != nil {
		return nil, errors.New("找不到该学校")
	}

	common.Log.Info("school ", util.Struct2Json(&school))

	return school, err
}

interface{} 转 string 工具类

// Strval 获取变量的字符串值
// 浮点型 3.0将会转换成字符串3, "3"
// 非数值或字符类型的变量将会被转换成JSON格式字符串
func Strval(value interface{}) string {
	var key string
	if value == nil {
		return key
	}

	switch value.(type) {
	case float64:
		ft := value.(float64)
		key = strconv.FormatFloat(ft, 'f', -1, 64)
	case float32:
		ft := value.(float32)
		key = strconv.FormatFloat(float64(ft), 'f', -1, 64)
	case int:
		it := value.(int)
		key = strconv.Itoa(it)
	case uint:
		it := value.(uint)
		key = strconv.Itoa(int(it))
	case int8:
		it := value.(int8)
		key = strconv.Itoa(int(it))
	case uint8:
		it := value.(uint8)
		key = strconv.Itoa(int(it))
	case int16:
		it := value.(int16)
		key = strconv.Itoa(int(it))
	case uint16:
		it := value.(uint16)
		key = strconv.Itoa(int(it))
	case int32:
		it := value.(int32)
		key = strconv.Itoa(int(it))
	case uint32:
		it := value.(uint32)
		key = strconv.Itoa(int(it))
	case int64:
		it := value.(int64)
		key = strconv.FormatInt(it, 10)
	case uint64:
		it := value.(uint64)
		key = strconv.FormatUint(it, 10)
	case string:
		key = value.(string)
	case []byte:
		key = string(value.([]byte))
	default:
		newValue, _ := json.Marshal(value)
		key = string(newValue)
	}

	return key
}