Go:程序结构

news2025/4/16 2:48:20

文章目录

  • 名称
  • 声明
  • 变量
    • 短变量声明
    • 指针
    • new 函数
    • 变量的生命周期
  • 赋值
    • 多重赋值
    • 可赋值性
  • 类型声明
  • 包和文件
    • 导入
    • 包初始化
  • 作用域

名称

命名规则

  • 通用规则:函数、变量、常量、类型、语句标签和包的名称,开头须是字母(Unicode 字符 )或下划线,后续可跟任意数量字符、数字和下划线,且区分大小写,如heapSortHeapsort是不同名称 。
  • 关键字:Go 有 25 个关键字,如breakcasefunc等,只能用于语法规定处,不能作为名称 。

image.png

  • 预声明名称:有一些预声明的常量(truefalseiotanil )、类型(intfloat32boolstring等 )和函数(makeappendlen等 ),这些名称虽可在声明中使用,但要注意冲突风险 。

image.png

可见性规则

  • 函数内声明的实体仅在函数局部有效;函数外声明的实体对包内所有源文件可见 。名称首字母大小写决定其在包间的可见性,大写开头的名称是导出的,可被包外程序引用,如fmt包的Printf ;包名一般由小写字母组成 。

命名风格

  • 长度:名称无长度限制,但习惯上,作用域小的局部变量倾向用短名称,如i ;作用域大的使用长且有意义的名称 。
  • 格式:Go 程序员常用 “驼峰式” 风格,由单词组合的名称用大写字母区分单词,如QuoteRuneToASCII ,而非下划线分隔形式;首字母缩写词通常保持相同大小写 。

声明

声明的种类与作用

  • 声明用于给程序实体命名并设定属性,Go 语言主要有变量(var)、常量(const)、类型(type)和函数(func)这 4 种声明 。

程序结构中的声明顺序

  • Go 程序由一个或多个.go文件组成,文件以package声明开头表明所属包,接着是import声明导入所需包,之后包级别的类型、变量、常量、函数声明顺序无严格要求 。
package main

import "fmt"

const boilingF = 212.0

func main() {
	var f = boilingF
	var c = (f - 32) * 5 / 9
	fmt.Printf("boiling point = %g°F or %g°C\n", f, c)
}
  • boiling程序:展示了一个计算并输出水沸点(华氏温度和摄氏温度 )的程序 。const boilingF = 212.0是包级常量声明 。包级声明在包内所有源文件可见,局部声明仅在声明所在函数内可见 。
func main() {
	const freezingF, boilingF = 32.0, 212.0
	fmt.Printf("%g°F = %g°C\n", freezingF, fToC(freezingF))
	fmt.Printf("%g°F = %g°C\n", boilingF, fToC(boilingF))
}

func fToC(f float64) float64 {
	return (f - 32) * 5 / 9
}
  • ftoc程序:实现华氏温度到摄氏温度的转换 。

变量

变量声明的形式

  • var声明变量,通用形式为var name type = expression ,可省略类型或表达式之一,但不能都省略 。省略类型时,变量类型由初始化表达式决定;省略表达式时,变量初始值为对应类型零值 。如var s strings初始值为空字符串 。

零值机制

  • Go 语言中所有变量都有零值,数字为 0,布尔值为false ,字符串为"" ,接口和引用类型(切片、指针、映射、通道、函数 )为nil ,复合类型(数组、结构体 )零值是其元素或成员零值 。零值机制避免未初始化变量问题,简化代码 。

变量列表声明

  • 可同时声明多个变量并初始化,如var i, j, k int声明三个int类型变量,var b, f, s = true, 2.3, "four"省略类型声明不同类型变量 。

变量初始化方式

  • 初始值可以是字面量或任意表达式 。包级变量初始化在main函数开始前进行,局部变量在函数执行期间初始化 。还可通过调用返回多个值的函数初始化变量,如var f, err = os.Open(name)os.Open返回文件和错误值 。

短变量声明

形式与原理

  • 在函数中,短变量声明用name := expression形式声明和初始化局部变量 ,变量name的类型由表达式expression的类型决定 。如anim := gif.GIF{LoopCount: nframes}anim类型由gif.GIF结构体类型确定 。

适用场景与对比

  • 因其简洁灵活,主要用于局部变量声明和初始化 。var声明则多用于变量类型与初始化表达式类型不一致,或初始值不重要、后续才赋值的情况 。

多个变量声明

  • 可同时声明多个变量并初始化,如i, j := 0, 1 ,但要注意仅在对可读性有帮助时使用 ,比如for循环初始化 。同时要区分:=(声明 )和=(赋值 ),避免与多重赋值混淆 。

调用多返回值函数

  • 短变量声明可用于调用像os.Open这样返回多个值的函数,如f, err := os.Open(name) ,获取文件和错误值 。

注意事项

  • 短变量声明不一定要声明所有左边变量,若已有变量在同一词法块中声明,新声明等同于赋值 。例如in, err := os.Open(infile)声明新变量,out, err := os.Create(outfile)err已有声明则为赋值 。
  • 短变量声明至少声明一个新变量,否则编译报错 ,如f, err := os.Open(infile)f, err := os.Create(outfile)(错误,无新变量 ) 。

指针

基本概念

  • 定义:指针的值是变量的地址,可在不知变量名字时间接读取或更新变量值 。如变量var x int&x获取指向x的指针,类型为*int ,指针p指向x时,*p可获取或更新x的值 。
  • 零值与比较:指针类型零值是nil ,测试p != nil可判断指针是否指向变量 。两个指针仅在指向同一变量或都为nil时相等 。

指针与变量

  • 聚合类型变量(结构体成员、数组元素 )都是变量,有地址 。变量的表达式是唯一能应用取地址操作符&的表达式 。

函数与指针

  • 返回局部变量指针:函数可返回局部变量地址,且局部变量在函数返回后依然存在,如func f() *int返回指向局部变量v的指针 。
  • 指针作为函数参数:传递指针参数给函数,能让函数更新间接传递的变量值 ,如func incr(p *int) int函数递增指针所指变量值并返回新值 。

flag包中的应用

指针在flag包中很关键,用于通过命令行参数设置程序内变量值 。

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

func main() {
	flag.Parse()
	fmt.Print(strings.Join(flag.Args(), *sep))
	if !*n {
		fmt.Println()
	}
}

实现var n = flag.Bool("n", false, "omit trailing newline")var sep = flag.String("s", " ", "separator")创建布尔和字符串标识变量,nsep是指针,需通过*n*sep访问 。运行程序时,先调用flag.Parse更新标识变量默认值,非标识参数可从flag.Args()获取 ,若flag.Parse出错,程序输出帮助信息并以os.Exit(2)结束 。

new 函数

功能与用法

  • new(T)用于创建一个未命名的T类型变量,初始化为T类型的零值,并返回其地址(地址类型为*T )。例如p := new(int) ,创建了一个未命名的int类型变量,p是指向该变量的指针,初始值为 0 ,后续可通过*p操作该变量,如*p = 2修改其值 。

与普通变量声明对比

  • new创建的变量和普通局部变量取地址操作类似,只是无需为变量命名,属于语法上的便利,并非基础概念 。如func newInt() *int { return new(int) }func newInt() *int { var dummy int; return &dummy } ,二者功能相同 。

调用特性

  • 每次调用new返回具有唯一地址的不同变量,如p := new(int); q := new(int); fmt.Println(p == q)输出false 。但对于类型不携带信息且为零值的情况(如struct{}[0]int ),当前实现中它们地址相同 。

使用频率与重定义

  • 因最常见未命名变量多为结构体类型,语法较复杂,所以new函数使用相对较少 。
  • new是预声明函数,不是关键字,可在函数内重定义为其他类型,如func delta(old, new int) int { return new - old } ,但在此函数内,内置new函数不可用 。

变量的生命周期

包级别变量:生命周期贯穿整个程序执行时间 。

局部变量:具有动态生命周期,每次执行声明语句时创建新实体,当变量变得不可访问时,其占用存储空间被回收 。函数参数和返回值也属于局部变量,在函数被调用时创建 。

垃圾回收与变量可达性

  • 垃圾回收器通过追踪变量的引用路径判断是否回收变量 。包级别变量和当前执行函数的局部变量可作为追溯源头,若变量路径不存在即不可访问,就会被回收 。局部变量生命周期取决于其是否可达,即便包含它的循环结束,只要仍可达,就可能继续存在 。

变量的存储分配

  • 编译器可选择在堆或栈上分配变量空间,此选择并非基于varnew关键字 。
var global *int
func f() {
    var x int
    x = 1
    global = &x
}

func g() {
    y := new(int)
    *y = 1
}
  • 函数f中局部变量x ,因在函数返回后仍可通过global变量访问(即从f中逃逸 ),所以使用堆空间;而函数g中用new创建的变量*y ,在函数返回后不可访问,编译器可在栈上分配 。
  • 理解变量逃逸概念对性能优化有帮助,变量逃逸需额外内存分配 。同时垃圾回收虽有助于编写正确程序,但要关注内存负担,了解变量生命周期对编写高效程序很重要,避免长生命周期对象持有短生命周期对象不必要的指针,影响垃圾回收 。

赋值

基本形式:赋值语句用于更新变量的值,最简形式由赋值符=、左边变量和右边表达式组成 。多种赋值场景:

  • 有名称变量:如x = 1 ,直接给变量x赋值 。
  • 间接变量(指针 )*p = true ,通过指针p给其所指变量赋值 。
  • 结构体成员person.name = "bob" ,给结构体personname成员赋值 。
  • 数组、切片或映射元素count[x] = count[x] * scale ,更新对应索引处元素值 。

赋值操作符

  • 算术和二进制位操作符都有对应的赋值操作符,如count[x] *= scale等价于count[x] = count[x] * scale ,可避免表达式中重复书写变量 。

数字++和–

  • 数字变量可通过++--进行递增递减操作 ,v++等同于v = v + 1v--等同于v = v - 1 。Go 中没有前置++--,只有后置++--,且无返回值。

多重赋值

概念:允许一次给多个变量赋值,在实际更新变量前,会先推演右边所有表达式 。

应用场景

  • 交换变量值:如x, y = y, x ,可直接交换xy的值;a[i], a[j] = a[j], a[i]用于交换数组元素 。
  • 计算最大公约数:在gcd函数中,for y != 0 { x, y = y, x%y } ,通过多重赋值不断更新xy的值来计算最大公约数 。
  • 计算斐波那契数列fib函数里,for i := 0; i < n; i++ { x, y = y, x+y } ,利用多重赋值迭代计算斐波那契数列第n个数 。
  • 紧凑赋值序列:如i, j, k = 2, 3, 5 ,可一次性给多个变量赋值 。

注意:从风格上,若表达式复杂,建议避免使用多重赋值,用独立语句更易读 。当赋值语句中使用有多个返回值的函数调用时,左边变量个数要与函数返回值个数一致,如f, err = os.Open("foo.txt")

特殊情况

  • 函数常通过额外返回值指示错误等情况 。
  • 一些操作(map 查询、类型断言、通道接收 )在赋值语句中会产生额外布尔型结果,如v, ok = m[key](map 查询 )、v, ok = x.(T)(类型断言 )、v, ok = <-ch(通道接收 ) 。
  • 如同变量声明,可将不需要的值赋给空白标识符_ ,如_, err = io.Copy(dst, src)(丢弃字节个数 )、_, ok = x.(T)(检查类型但丢弃结果 ) 。

可赋值性

  • 显式赋值:通过赋值语句(如x = 1 )进行的赋值操作 。
  • 隐式赋值:函数调用时将参数值赋给对应参数变量、return语句将操作数赋给结果变量,以及复合类型字面量表达式对元素的赋值(如medals := []string{"gold", "silver", "bronze"} ,等同于medals[0] = "gold"; medals[1] = "silver"; medals[2] = "bronze" ) 。map和通道元素也有类似隐式赋值 。

可赋值性规则

  • 无论是隐式还是显式赋值,当左边变量和右边值的类型相同时,赋值合法 ,即值对于变量类型可赋值时才合法 。对于已讨论类型,类型需精准匹配,nil可赋给任何接口变量或引用类型 。常量有更灵活可赋值性规则以避免显式转换 。

与比较操作的关系

  • 两个值用==!=比较时,与可赋值性相关,比较中第一个操作数相对于第二个操作数的类型必须是可赋值的,或可反向赋值 ,后续引入新类型时会解释其可比较性规则 。

类型声明

  • 概念:用type声明定义新的命名类型,与某个已有类型使用相同底层类型 ,形式为type name underlying - type

  • 作用:区分底层类型的不同使用场景,避免混淆 。例如,在温度转换程序中,定义type Celsius float64type Fahrenheit float64 ,虽底层类型都是float64 ,但分别代表摄氏温度和华氏温度,防止不同计量单位温度值的无意合并 。

  • 类型转换操作:每个类型T都有对应的类型转换操作T(x) ,将值x转换为类型T 。如Celsius(t)Fahrenheit(t)是类型转换,不会改变值和表达方式,仅改变显式意义 。

  • 类型转换规则:具有相同底层类型或指向相同底层类型变量的未命名指针类型可相互转换,且不改变值的表达方式 。数字类型、字符串和一些切片类型间转换会改变值的表达方式,如浮点型转整型会丢失小数部分 ,但运行时转换不会失败 。

比较与操作

  • 命名类型的值可与其相同类型的值或底层类型相同的未命名类型的值,通过==<等比较操作符进行比较 ,不同命名类型的值不能直接比较 。
  • 命名类型可使用与底层类型相同的算术操作符 ,如CelsiusFahrenheit类型可进行与float64相同的算术运算 。

类型的方法关联

  • Celsius类型为例,可声明关联方法,如func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) } ,当通过fmt包输出变量时,可控制类型值的显示方式 。

包和文件

  • 作用:类似于其他语言的库或模块,用于支持模块化、封装、编译隔离和重用 。
  • 概念:包的源代码存于一个或多个.go文件,所在目录名尾部是包的导入路径 。包为声明提供独立命名空间,不同包中同名函数互不干扰 。通过控制标识符是否以大写字母开头,管理其对外可见性(导出标识符大写开头 ) 。

包的示例

package tempconv

import "fmt"

type Celsius float64
type Fahrenheit float64

const (
	AbsoluteZeroC Celsius = -273.15
	FreezingC     Celsius = 0
	BoilinfC      Celsius = 100
)

func (c Celsius) String() string    { return fmt.Sprintf("%g°C", c) }
func (f Fahrenheit) String() string { return fmt.Sprintf("%g°F", f) }
package tempconv

func CToF(c Celsius) Fahrenheit { return Fahrenheit(c * 9 / 5 + 32)}

func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9)}

以温度转换功能创建gopl.io/ch2/tempconv包为例:

  • 文件构成:包内有tempconv.goconv.go两个文件 。tempconv.go声明了CelsiusFahrenheit类型、相关常量,以及类型的String方法 ;conv.go包含温度转换函数CTOFFTOC
  • 包的使用:每个文件开头用package声明包名 。导入包后,可通过包名.成员名方式引用包内成员,如tempconv.CToF 。包级常量若大写开头,也可通过修饰名(如tempconv.AbsoluteZeroC )访问 。
  • 文档注释:包声明前应紧跟文档注释描述整个包,习惯在开头用一句话总结,一个包通常只有一个文件含文档注释,扩展注释一般放于名为doc.go的文件中 。

导入

概念

  • 在 Go 程序中,每个包通过导入路径(import path )这一唯一字符串标识,如"gopl.io/ch2/tempconv" 。语言规范未定义其来源和含义,由工具解释 。导入路径标注目录,该目录含包的.go源文件 。包名通常与导入路径最后一段匹配,如gopl.io/ch2/tempconv包名是tempconv

示例

package main

import (
	"fmt"
	"os"
	"strconv"

	"gopl.io/ch2/tempconv"
)

func main() {
	for _, arg := range os.Args[1:] {
		t, err := strconv.ParseFloat(arg, 64)
		if err != nil {
			fmt.Fprintf(os.Stderr, "cf: %v\n", err)
			os.Exit(1)
		}
		f := tempconv.Fahrenheit(t)
		c := tempconv.Celsius(t)
		fmt.Printf("%s = %s, %s = %s\n",
			f, tempconv.FToC(f), c, tempconv.CToF(c))
	}
}
  • cf程序为例,它导入"gopl.io/ch2/tempconv"包,将命令行参数转换为摄氏温度和华氏温度 。在main函数中,遍历命令行参数,先将参数转换为浮点数,再分别转换为FahrenheitCelsius类型,最后输出转换后的温度值 。
  • 导入声明可给导入的包绑定短名字(默认是包名 ),用于在文件中引用包内容,如tempconv.CToF 。也可设定可选名字避免冲突 。

检查机制

  • 若导入包但未在代码中引用,会触发错误,这有助于消除不再需要的依赖 。如调试时注释掉对包唯一引用的代码,会导致编译器报错,此时需注释或删除不必要的import

包初始化

变量

  • 包的初始化从包级变量开始,变量按声明顺序初始化,在依赖解析完成后,依据依赖顺序进行 。例如var a = b + cvar b = f()var c = 1func f() int { return c + 1 } ,先初始化c为 1 ,再调用f初始化b为 2 ,最后初始化a为 3 。若包由多个.go文件组成,初始化按编译器接收文件顺序进行(go工具会在调用编译器前对文件排序 ) 。

init函数

  • 对于一些初始化表达式不只是简单设置初始值的变量(如数据表 ),可使用init函数 。任何文件可包含任意数量init函数,其不能被调用或引用,在程序启动时,按声明顺序自动执行 。
  • 包的初始化按导入顺序进行,依赖顺序优先,被导入包先完成初始化 ,main包最后初始化 ,确保在main函数执行前所有包初始化完毕 。

示例

package popcount

var pc [256]byte

func init() {
	for i := range pc {
		pc[i] = pc[i / 2] + byte(i&1)
	}
}

func Popcount(x uint64) int {
	return int(pc[byte(x >> (0 * 8))] +
		pc[byte(x >> (1 * 8))] +
		pc[byte(x >> (2 * 8))] +
		pc[byte(x >> (3 * 8))] +
		pc[byte(x >> (4 * 8))] +
		pc[byte(x >> (5 * 8))] +
		pc[byte(x >> (6 * 8))] +
		pc[byte(x >> (7 * 8))])
}
  • popcount包为例,定义了PopCount函数用于统计uint64值中置位个数 。通过init函数预先计算结果表pcPopCount函数利用该表计算,避免 64 步计算 。init函数中for i := range pc循环只使用索引,也可写成for i, _ := range pc

作用域

与生命周期的区别

  • 声明的作用域是在程序文本中声明名字出现的区域,是编译时属性;变量的生命周期是变量在程序执行期间能被引用的起止时间,是运行时属性 。

  • 语法块:由大括号包围的语句序列,如循环体、函数体等,内部声明变量对外不可见 。

  • 词法块:可推广到没显式大括号包含的声明代码,包括全局块(含全部源代码 )、包、文件、forifswitch语句及switchselect语句中的条件部分 。显式大括号代码块也属词法块 。

作用域规则

  • 声明的词法块决定其作用域大小 。内置类型、函数、常量在全局块声明,对整个包可见,可在包内任何文件引用 。包级声明在包内文件可见 ,局部声明(如函数内变量声明 )仅在声明所在函数或部分语句内可用 。控制流标签(breakcontinuegoto使用的标签 )作用域是外层函数 。
  • 不同词法块可声明同名实体 ,但要避免滥用 。编译器从最内层封闭词法块到全局块查找名字声明,若未找到报 “undeclared name” 错误,内层声明会覆盖外层 。

词法块嵌套与变量作用域

  • 函数内词法块嵌套深,局部变量声明可能覆盖其他声明 。如for循环创建显式和隐式词法块,隐式词法块中声明变量作用域包括条件、后置语句及循环体本身 。ifswitch语句也会创建隐式词法块,条件对应一个块,每个case语句体对应一个块 ,且隐式词法块中初始化部分声明变量在后续语句可能不可见 。

包级别声明与作用域

  • 包级别声明顺序和作用域无关,可引用自身或后面声明(如递归类型和函数 ),但常量或变量声明引用自身会报错 。同时局部变量在if语句中作用域相关编译错误及解决办法 ,短变量声明对作用域的依赖
var cwd string
func init() {
    // cwd, err := os.Getwd() // 错误
    var err error
    cwd, err  = os.Getwd() // 正确
    // ...
}

for循环创建显式和隐式词法块,隐式词法块中声明变量作用域包括条件、后置语句及循环体本身 。ifswitch语句也会创建隐式词法块,条件对应一个块,每个case语句体对应一个块 ,且隐式词法块中初始化部分声明变量在后续语句可能不可见 。

包级别声明与作用域

  • 包级别声明顺序和作用域无关,可引用自身或后面声明(如递归类型和函数 ),但常量或变量声明引用自身会报错 。同时局部变量在if语句中作用域相关编译错误及解决办法 ,短变量声明对作用域的依赖
var cwd string
func init() {
    // cwd, err := os.Getwd() // 错误
    var err error
    cwd, err  = os.Getwd() // 正确
    // ...
}

参考资料:《Go程序设计语言》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2335651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 二分查找(bisect):排序数据的高效检索

二分查找&#xff1a;排序数据的高效检索 第二天清晨&#xff0c;李明早早来到了图书馆。今天他的研究目标是bisect模块&#xff0c;特别是其中的bisect_left和bisect_right函数。这些函数实现了二分查找算法&#xff0c;用于在已排序的序列中高效地查找元素或确定插入位置。 …

【数据结构】堆排序详细图解

堆排序目录 1、什么是堆&#xff1f;1.1、什么是大顶堆1.2、什么是小顶堆 2、堆排序的过程3、堆排序的图解3.1、将数组映射成一个完全二叉树3.2、将数组转变为一个大顶堆3.3、开始进行堆排序 4、堆排序代码 1、什么是堆&#xff1f; 堆的定义&#xff1a;在一棵完全二叉树中&a…

CST1016.基于Spring Boot+Vue高校竞赛管理系统

计算机/JAVA毕业设计 【CST1016.基于Spring BootVue高校竞赛管理系统】 【项目介绍】 高校竞赛管理系统&#xff0c;基于 DeepSeek Spring AI Spring Boot Vue 实现&#xff0c;功能丰富、界面精美 【业务模块】 系统共有两类用户&#xff0c;分别是学生用户和管理员用户&a…

安卓性能调优之-掉帧测试

掉帧指的是某一帧没有在规定时间内完成渲染&#xff0c;导致 UI 画面不流畅&#xff0c;产生视觉上的卡顿、跳帧现象。 Android目标帧率&#xff1a; 一般情况下&#xff0c;Android设备的屏幕刷新率是60Hz&#xff0c;即每秒需要渲染60帧&#xff08;Frame Per Second, FPS&a…

GPT-SoVITS:5 步实现 AI 语音克隆

在 AI 技术高速迭代的今天&#xff0c;语音合成早已突破”机械朗读“的局限 —— 从短视频创作者的虚拟配音、游戏角色的个性化声线&#xff0c;到智能客服的自然交互&#xff0c;GPT-SoVITS正凭借其强大的多模态融合能力&#xff0c;成为实现”AI 声音克隆“与“情感化语音生成…

记录:安装 Docker Desktop 时直接设置安装路径及容器存储路径

近期学用 deepseek 本地知识库的构建&#xff0c;准备尝试几个不同的 RAG 工具&#xff0c;结果基本都需要 Docker 支持&#xff0c;故又重新拾起 Docker 来安装&#xff0c;刚好看到个不用目录链接就可以直接设置安装路径的方法&#xff0c;就记录一下&#xff0c;以免以后忘…

算法训练之贪心

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…

Vagrant 安装指南:从零开始搭建开发环境

Vagrant 是一款强大的虚拟化工具&#xff0c;能够帮助开发者快速创建和管理轻量级的、可复制的开发环境。它通过与 VirtualBox、VMware 或 Hyper-V 等虚拟机提供程序结合使用&#xff0c;让你在本地轻松运行虚拟机。本文将详细介绍如何在 Windows、macOS 和 Linux 系统上安装 V…

APIGen-MT:高效生成多轮人机交互Agent数据的两阶段框架

APIGen-MT&#xff1a;高效生成多轮人机交互数据的两阶段框架 引言 随着人工智能技术的飞速发展&#xff0c;AI代理&#xff08;Agent&#xff09;已从简单的聊天机器人发展为能够执行复杂现实任务的系统&#xff0c;例如管理金融交易、安排预约和处理客户服务等。然而&#x…

【NLP】 21. Transformer整体流程概述 Encoder 与 Decoder架构对比

1. Transformer 整体流程概述 Transformer 模型的整个处理流程可以概括为从自注意力&#xff08;Self-Attention&#xff09;到多头注意力&#xff0c;再加上残差连接、层归一化、堆叠多层的结构。其核心思想是利用注意力机制对输入进行并行计算&#xff0c;从而避免传统 RNN …

《Vue Router实战教程》21.扩展 RouterLink

欢迎观看《Vue Router 实战&#xff08;第4版&#xff09;》视频课程 扩展 RouterLink RouterLink 组件提供了足够的 props 来满足大多数基本应用程序的需求&#xff0c;但它并未尝试涵盖所有可能的用例&#xff0c;在某些高级情况下&#xff0c;你可能会发现自己使用了 v-sl…

开发一个答题pk小程序的大致成本是多少

答题 PK 小程序通常指的是一种允许用户之间进行实时或异步答题竞赛的应用程序&#xff0c;可能结合PK答题、积分系统、排行榜等功能。 一、首先&#xff0c;确定答题 PK 小程序的基本功能模块。这可能包括用户注册登录、题库管理、题目类型&#xff08;单选、多选、判断等&am…

GPT-2 语言模型 - 模型训练

本节代码是一个完整的机器学习工作流程&#xff0c;用于训练一个基于GPT-2的语言模型。下面是对这段代码的详细解释&#xff1a; 文件目录如下 1. 初始化和数据准备 设置随机种子 random.seed(1002) 确保结果的可重复性。 定义参数 test_rate 0.2 context_length 128 tes…

科技项目验收测试包括哪些内容?有什么作用?

在现代科技快速发展的背景下&#xff0c;科技项目的验收测试已成为项目管理中的重要环节。科技项目验收测试是一种系统性的方法&#xff0c;旨在评估一个科技项目是否达到预定的技术指标和要求&#xff0c;确认项目的完成质量。该测试通常在项目实施完成后进行&#xff0c;通过…

websoket 学习笔记

目录 基本概念 工作原理 优势 应用场景 HTTP协议与 webSoket协议之间的对比 消息推送场景 1. 轮询&#xff08;Polling&#xff09; 2. 长轮询&#xff08;Long Polling&#xff09; 3. 服务器发送事件&#xff08;Server-Sent Events, SSE&#xff09; 4. WebSocket…

博途 TIA Portal之1200做从站与汇川EASY的TCP通讯

上篇我们写到了博途做主站与汇川EASY的通讯。通讯操作起来很简单,当然所谓的简单,也是相对的,如果操作成功一次,那么后面就很容易了, 如果操作不成功,就会很遭心。本篇我们将1200做从站,与汇川EASY做主站进行TCP的通讯。 1、硬件准备 1200PLC一台,带调试助手的PC机一…

【数据结构_6下篇】有关链表的oj题

思路&#xff1a; 1.分别求出这两个链表的长度 2.创建两个引用&#xff0c;指向两个链表的头节点&#xff1b;找到长度长的链表&#xff0c;让她的引用先走差值步数 3.让这两个引用&#xff0c;同时往后走&#xff0c;每个循环各自走一步 然后再判定两个引用是否指向同一个…

vscode+wsl 运行编译 c++

linux 的 windows 子系统&#xff08;wsl&#xff09;是 windows 的一项功能&#xff0c;可以安装 Linux 的发行版&#xff0c;例如&#xff08;Ubuntu&#xff0c;Kali&#xff0c;Arch Linux&#xff09;等&#xff0c;从而可以直接在 windows 下使用 Linux 应用程序&#xf…

关于 Spring Boot 微服务解决方案的对比,并以 Spring Cloud Alibaba 为例,详细说明其核心组件的使用方式、配置及代码示例

以下是关于 Spring Boot 微服务解决方案的对比&#xff0c;并以 Spring Cloud Alibaba 为例&#xff0c;详细说明其核心组件的使用方式、配置及代码示例&#xff1a; 关于 Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案! https://sca.aliyun.com/?spm7145af80…

VS 基于git工程编译版本自动添加版本号

目录 概要 实现方案 概要 最近在用visual Studio 开发MFC项目时&#xff0c;需要在release版本编译后的exe文件自动追加版本信息。 由于我们用的git工程管理&#xff0c;即需要基于最新的git 提交来打版本。 比如&#xff1a; MFCApplication_V1.0.2_9.exe 由于git 提交信…