当前位置: 首页 > news >正文

建站行业解决方案网站更改关键词

建站行业解决方案,网站更改关键词,网络设计思路,网站表单变量 在Go语言中,变量的定义和初始化是编程的基础部分。Go提供了多种方式来声明和初始化变量,以适应不同的使用场景。 基本变量声明 使用var关键字: 使用var关键字可以在函数内部或外部声明变量。如果在函数外部声明,该变量为全…

变量

在Go语言中,变量的定义和初始化是编程的基础部分。Go提供了多种方式来声明和初始化变量,以适应不同的使用场景。

基本变量声明

  1. 使用var关键字
    使用var关键字可以在函数内部或外部声明变量。如果在函数外部声明,该变量为全局变量。

    var str1 string = "变量1"
    var int1 int = 123
    fmt.Println(str1, int1)
    

    如果已经明确了初始值,则可以省略类型信息,让编译器自动推断类型:

    var str2 = "变量2"
    var int2 = 123
    fmt.Println(str2, int2)
    
  2. 短变量声明
    在函数内部,你可以使用更简洁的短变量声明(Short variable declarations)方式 :=。这种方式同时进行了声明和初始化,并且类型由右侧表达式推断得出。

    func main() {str3 := "变量3"int3 := 123fmt.Println(str3, int3)
    }
    

多重赋值

Go支持多个变量同时赋值:

	//var a, b, c = "1", 2, 3.55a, b, c := "1", 2, 3.55// 使用 reflect 包中的 .TypeOf 函数。返回变量的类型信息fmt.Println("a的类型为:", reflect.TypeOf(a))fmt.Println("b的类型为:", reflect.TypeOf(b))fmt.Println("c的类型为:", reflect.TypeOf(c))
	// 为相同类型的变量在同一行上声明和赋值//var a, b, c int = "1", 2, 3 // 错误,不能将字符串赋值给整数变量。 Go 不支持在同一行中为不同类型变量分配类型。var a, b, c int = 1, 2, 3fmt.Println("a的类型为:", reflect.TypeOf(a))fmt.Println("b的类型为:", reflect.TypeOf(b))fmt.Println("c的类型为:", reflect.TypeOf(c))

块声明(block declaration)语法。这种方式允许在一个 var 语句中声明多个变量,并为它们赋初始值。

	var (a = 1111b = "bbb"c bool)fmt.Println(a, b, c)

零值(Zero Values)

在Go中,如果你只是声明一个变量而没有给它赋初值,则会自动被赋予该类型的零值:

  • 数字类型(整型、浮点型等)的零值是 0
  • 布尔型的零值是 false
  • 字符串的零值是空字符串 ""
  • 指针、切片、映射、通道、函数以及接口的零值都是 nil

例如:

	var a stringvar b intvar c float64var d boolfmt.Printf("a的值:【%v】\n", a)fmt.Printf("b的值:【%v】\n", b)fmt.Printf("c的值:【%v】\n", c)fmt.Printf("d的值:【%v】\n", d)/*输出结果为:a的值:【】b的值:【0】c的值:【0】d的值:【false】*/

作用域

在Go语言中,作用域(Scope)指的是一个变量或者函数名字在程序中可以被访问的区域。

  1. 全局作用域

    • 如果一个变量是在所有函数之外定义的,则它被认为是全局变量,可以在整个包内部任何位置使用。如果需要在其他包中使用这些全局变量或函数,则它们必须首字母大写。

    test1.go

    package mainimport "fmt"var name = "全局变量"func main() {// 在同一包下的不同文件中可以访问并且修改全局变量printGlobalVar()fmt.Println(name)
    }
    

    test2.go

    package mainimport "fmt"func printGlobalVar() {fmt.Println(name)name = "修改后的全局变量"
    }
    
  2. 包级别作用域

    • 在同一个包内部,当变量或者常数被定义在所有函数之外时(但不一定非得在文件最顶端),这些标识符将对整个包内部可见。这意味着同一包下不同文件中的代码也可以访问这些变量。
    • 全局作用域的变量首字母小写,其实就相当于包级别作用域的变量
  3. 文件级别作用域

    • 这个概念在 Go 语言中并不存在。Go 语言中最小的作用域单位是包级别作用域。
  4. 局部作用域

    • 在函数内定义的变量只能在该函数内部访问,并且这种限制也适应于该函数内定义的其他嵌套块结构如if条件、循环等。
    func printLocalVar() {var localVar = "局部变量"fmt.Println(localVar)
    }
    
  5. 块级别作用域

    • Go 语言支持诸如 if、for、switch 等控制结构,并且每个结构都会引入新的块范围。例如,在 if 语句中声明并初始化一个新变量,在该 if 块及其子块中该变量是可见和可访问的,但超出此范围后就不再可见。
    func printBlockVar() {var localVar = "局部变量"// 代码块{var blockVar = "块级变量"fmt.Println(blockVar)fmt.Println(localVar) // 可以访问局部变量}//fmt.Println(blockVar) // 报错,无法访问块级变量
    }
    

赋值过程

赋值过程及内存相关的知识,通过以下代码做分析

	name := "这是一段字符串"nickname := name
  1. 声明并初始化 name
    • name 被声明为一个新的局部变量,并且类型被推断为字符串(string)。它指向一个内存位置,该位置存储着字符串 "这是一段字符串"
  2. 声明并初始化 nickname
    • 接下来,另一个新变量 nickname 被声明,并使用短变量声明方式同时进行初始化。
    • 在这个赋值操作中,由于字符串在Go中是不可变的,并且赋值操作只是复制了引用(而非数据本身),因此 nickname 也会指向同一块内存地址,即指向 "这是一段字符串" 的那块内存。
    • 注意!namenickname 都指向同一个字符串字面值 "这是一段字符串" 的实际数据。这意味着他们共享相同的底层字节数组。然而,每个字符串变量(如 namenickname)本身也是一个独立的实体,拥有自己的内存地址。
  3. 内存共享
    • 重要的是理解,在这种情况下,没有新的字符串数据被创建。两个变量 namenickname 实际上共享相同的底层数据。这意味着对于只读数据如字符串来说非常高效。
  4. 垃圾回收考虑
    • 在Go语言中,当没有任何引用指向某块内存时(即不再有任何方式访问该内存),这块内存就可能被标记为可回收。只要任何一个变量仍然引用着那块内存(即使其中一个已经超出了作用域),那么该内存就不会被垃圾回收器回收。只有当所有引用(name和nickname)都消失时才会释放相关资源。

结合代码说明

package mainimport ("fmt""unsafe" // 代码使用 `unsafe` 包将变量的地址转换为 `stringHeader` 类型的指针,以便访问字符串的底层数据指针。
)func main() {// 情况1 变量地址不同,指向的值地址相同name := "这是一段字符串"nickname := namefmt.Println("============打印变量的地址信息============")fmt.Printf("变量'name'  地址:【%p】\n", &name)fmt.Printf("变量'nickname'  地址:【%p】\n", &nickname)// 使用unsafe包来获取字符串底层数据指针nameDataPointer1 := (*stringHeader)(unsafe.Pointer(&name)).DatanicknameDataPointer1 := (*stringHeader)(unsafe.Pointer(&nickname)).Datafmt.Printf("'name'数据的指向地址: %x\n", nameDataPointer1)fmt.Printf("'nickname'数据的指向地址: %x\n\n", nicknameDataPointer1)// 情况2 变量地址不同,指向的值地址也相同,因为字符串是不可变的nickname = "这是一段字符串"fmt.Println("============打印变量的地址信息============")fmt.Printf("变量'name'  地址:【%p】\n", &name)fmt.Printf("变量'nickname'  地址:【%p】\n", &nickname)// 使用unsafe包来获取字符串底层数据指针nameDataPointer2 := (*stringHeader)(unsafe.Pointer(&name)).DatanicknameDataPointer2 := (*stringHeader)(unsafe.Pointer(&nickname)).Datafmt.Printf("'name'数据的指向地址: %x\n", nameDataPointer2)fmt.Printf("'nickname'数据的指向地址: %x\n\n", nicknameDataPointer2)// 情况3 变量地址不同,指向的值地址不同nickname = "这是一段字符串!"fmt.Println("============打印变量的地址信息============")fmt.Printf("变量'name'  地址:【%p】\n", &name)fmt.Printf("变量'nickname'  地址:【%p】\n", &nickname)// 使用unsafe包来获取字符串底层数据指针nameDataPointer3 := (*stringHeader)(unsafe.Pointer(&name)).DatanicknameDataPointer3 := (*stringHeader)(unsafe.Pointer(&nickname)).Datafmt.Printf("'name'数据的指向地址: %x\n", nameDataPointer3)fmt.Printf("'nickname'数据的指向地址: %x\n\n", nicknameDataPointer3)}/*
stringHeader用于获取字符串的底层数据指针,这个结构体是 Go 语言中字符串的内部表示。
`Data` 是一个 `uintptr` 类型的字段,它用来存储指向字符串数据的指针
`Len` 存储字符串的长度。
*/
type stringHeader struct {Data uintptr // 指向实际数据的指针Len  int     // 字符串的长度
}

打印结果

============打印变量的地址信息============
变量'name'  地址:【0xc000014070】
变量'nickname'  地址:【0xc000014080】
'name'数据的指向地址: 2f2a8fd
'nickname'数据的指向地址: 2f2a8fd============打印变量的地址信息============
变量'name'  地址:【0xc000014070】
变量'nickname'  地址:【0xc000014080】
'name'数据的指向地址: 2f2a8fd
'nickname'数据的指向地址: 2f2a8fd============打印变量的地址信息============
变量'name'  地址:【0xc000014070】
变量'nickname'  地址:【0xc000014080】
'name'数据的指向地址: 2f2a8fd
'nickname'数据的指向地址: 2f2b3eb

这段 Go 语言代码演示了字符串在不同情况下的内存地址和底层数据指针的变化。代码分为三个部分,每部分都打印了变量的内存地址和它们指向的字符串数据的地址。这里使用了 unsafe 包来操作指针和内存,这是 Go 语言中一个特殊的包,允许程序绕过类型安全性的限制。

  1. 情况1:创建了两个变量 namenickname,它们被赋予了同一个字符串字面量。由于字符串是不可变的,nickname 实际上是对 name 所指向的字符串的一个别名。因此,尽管 namenickname 作为变量有不同的内存地址,它们指向的字符串数据的地址是相同的。

  2. 情况2nickname 被重新赋值为与 name 相同的字符串字面量。由于字符串是不可变的,这个新的字符串字面量可能会指向与 name 相同的内存地址,或者可能会创建一个新的字符串实例,这取决于 Go 运行时的优化。在这个例子中,由于字符串内容相同,nickname 可能指向了与 name 相同的内存地址。

  3. 情况3nickname 被重新赋值为一个不同的字符串字面量,这次字符串内容与 name 不同。由于字符串是不可变的,这个新的字符串字面量将创建一个新的内存地址来存储这个新的字符串内容。因此,nickname 将指向一个新的内存地址,与 name 所指向的地址不同。

待后面我们展开学习go中的 *(指针)与&(地址)后,再回头来理解上面的赋值和内存相关,会容易理解很多。

http://www.yayakq.cn/news/15184/

相关文章:

  • 活动网站推广方案男生做网站运营的前景
  • 临时工200一天一结重庆seo网络推广优化
  • 网站建设标准简约一条龙建设网站
  • 遵义本地网站网站关键字工具
  • 怎样在网站是做宣传云主机做网站域名打不开
  • 中兴的网站谁做的深圳专业网站建设
  • 网站备案管理系统登录不上去wordpress插件地址
  • 受欢迎的做pc端网站雅虎网站优化怎么做
  • 中国做出口的网站平台网站开发现在主要用什么语言
  • 用什么软件做介绍视频网站wordpress站点logo多大合适
  • html 模板网站适合小学生的新闻事件
  • 数据服务网站策划方案目前市面上做网站的程序
  • h5在哪个网站中做网络舆情分析研判报告
  • 网站建设郑州python 网站开发实例教程
  • 长沙精品网站制作网站内容页做301
  • 怎么做网站的营销创意产品设计书
  • 成都物流网站建设小学生一分钟新闻播报
  • 企业网站规划与设计网络服务提供者接到权利人
  • 网站开发作业总结天元建设集团有限公司北京分公司
  • 做网站的技巧网站构建的基本流程
  • zepto网站开发个人网站cms系统
  • 福州企业建站服务郑州看妇科最好的医院是哪里
  • 是想建个网站 用本地做服务器2023最近的新闻大事10条
  • 怎么seo网站关键词优化重庆建设教育培训管理系统网站
  • 自助手机建站青海省建设厅网站备案资料
  • 免费网站设计什么价格网站的导航栏设计文本
  • 北京门户网站制作学ui设计
  • 网站备案 多ipwordpress安装后慢的不行
  • 免费建站网站一级大dw可以做wordpress
  • 石家庄哪里有网站建设建设成一个网站的程序