Go基础知识梳理

本文介绍了Go语言的基础知识,包括指针的使用,如指针的声明、比较和方法;变量的作用域规则,以及如何在函数内外声明和访问变量;此外还讲解了new函数用于初始化并返回变量地址的功能。通过对这些概念的理解,有助于深入掌握Go语言的编程基础。

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

1、名称

  • 指针
    Go提供了指针,它的值是变量的地址。使用& 操作符可以获取一个变量的地址,使用* 操作符可以获取指针引用的变量的值,但是指针不支持算数运算。
    指针类型的零值是 nil。测试 p != nil,结果是 true 说明 p 指向一个变量。指针是可比较的,两个指针当且仅当指针指向同一个变量或者两者都是 nil 的情况下才是相等的。
	var x, y int
	fmt.Println(&x == &x, &x == &y, &x == nil) // "true false false"
  • 方法和接口
    一个关联了命名类型的函数称为方法。Go里面的方法可以关联到几乎所有的命名类型。
  • 指针对于 flag 包是很关键的,它使用程序的命令行参数来设置整个程序内某些变量的值。
package main

import (
	"flag"
	"fmt"
	"strings"
)

var n = flag.Bool("n", false, "omit trailing newline")
var sep = flag.String("s", " ","separator")

func main()  {
	flag.Parse()
	fmt.Println(strings.Join(flag.Args(), *sep))
	if !*n {
		fmt.Println()
	}
}
  • 变量的声明周期
    编译器可以选择使用堆或者栈上的空间来进行分配,令人惊奇的是,这个选择不是基于使用 var 或 new 关键字来声明变量。
var global *int

func f()  {
	var x int
	x = 1
	global = &x
	
}

func g()  {
	y := new(int)
	*y = 1
}

在这里, x 一定使用堆空间,因为它在f 函数返回以后还可以从 global 变量访问,尽管它被声明为一个局部变量。这种情况我们说 x 从 f 中逃逸。相反,当 g 函数返回时,变量 *y 变得不可访问,可回收。因为 *y 没有从g 中逃逸,索引编译器可以安全地在粘上分配 *y,即使使用 new 函数创建它。

  • 类型声明
    通过 == 和 < 之类的比较操作符,命名类型的值可以与其相同类型的值或者底层类型相同的未命名类型的值比较。但是不同命名类型的值不能直接比较:
type Celsius float64
type Fahrenheit float64


func main()  {

	var c Celsius
	var f Fahrenheit
	
	fmt.Println(c == 0)   // "true"
	fmt.Println(f >= 0)   // "true"
	fmt.Println(c == f)   // "编译错误: 类型不匹配"
	fmt.Println(c == Celsius(f)) // "true"

}

2、new 函数

另外一种创建变量的方式是使用内置的 new 函数。表达式 new(T) 创建一个未命名的T类型变量。初始化为T类型的零值,并返回其地址(地址类型为 *T)

	p := new(int)   // *int 类型的p,指向未命名的 int 变量
	fmt.Println(*p)  // 输出 "0"
	*p = 2 // 把未命名的 int 设置为2
	fmt.Println(*p)   // 输出 "2"

下面两个 newInt 函数有相同的行为,每一次调用 new 返回一个具有唯一地址的不同变量。

func newInt() *int {
	return new(int)
}


func newInt() *int {
	var dumpy int
	return &dumpy
	
}

3、作用域

如果一个实体在函数中声明,它只在函数局部有效。如果声明在函数外,它将对包里面的所有源文件可见。实体第一个字母的大小写决定其可见性是否跨包。如果名称以大写字母开头,它是导出的,意味着它对包外是可见和可访问的,可以被自己包之外的其他程序所引用。包名本身总是由小写字母组成。

当编译器遇到一个名字的引用时,将从内部的封闭词法块到全局块寻找其声明。如果没有找到,它会报 “undeclared name” 错误;如果在内层和外层块存在这个声明,内层的将先被找到。这种情况下,内层声明将覆盖外部声明,使它不可访问:

func main()  {
	x := "hello!"
	for i := 0; i < len(x); i++ {
		x := x[i]
		if x != '!' {
			x = x + 'A' - 'a'
			fmt.Printf("%c", x)   // "HELLO" (每次迭代一个字母)
		}
	}

}

func main()  {
	x := "hello!"
	for _, x := range x {
		x = x + 'A' - 'a'
		fmt.Printf("%c", x)  // "HELLO" (每次迭代一个字母)
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值