首页 > 其他分享 >go语言基础-语言的核心结构与技术之基本结构要素

go语言基础-语言的核心结构与技术之基本结构要素

时间:2023-08-04 09:34:35浏览次数:43  
标签:函数 fmt 类型 使用 go 结构 main 可以 语言

package main

import "fmt"

func main() {
    fmt.Println("hello,world")  
}

上述伪代码可以看到,学习go语言的基本语法,接下来,针对这段伪代码分析

package main

封装的概念,导入与可见性

包是构造代码的一种方式:每个程序都由包(通常简称为pkg)的概念组成,可以使用自身的包或者从其他包中导入内容。

类似于其他一些编程语言中的类库或命名空间的概念,每个Go文件都属于且只属于一个包。一个包可以由许多.go组成的。

你必须在源文件中非注释的第一行指明该文件属于哪个包,例如: 。package main表示package main一个可独立执行的程序,每个 Go 应用程序都包含一个名为main的包。

一个应用程序可以包含不同的包,而且即使你只使用主包也不必把所有的代码都写在一个巨大的文件里:你可以使用更小的文件,并且在每个文件中非注释的第一个行都使用package main来指明这些文件都属于main包。如果你打算编译包名不是主要的源文件,例如pack1,编译后产生的目标文件将pack1.a不是执行程序。另外要注意的是,所有的包名都应该使用小写字母。

import "fmt"

一个Go程序是通过import关键字将一组包链接在一起的。

import "fmt"告诉Go编译器这个程序需要使用fmt包(的函数,或其他元素),fmt包实现了格式化IO(输入/输出)的函数。包名被封闭在半角双引号中""。如果你打算从已编译的包中导入并加载公开声明的方法,不需要插入已编译包的源代码。

如果需要导入多个包,可以分别导入:

import "fmt"
import "os"

或者

import "fmt"; import "os"
但是还有更短且更优雅的方法(被称为因式关键字划分,该方法同样适用于constvartype的声明或定义):
import (
   "fmt"
   "os"
)

 当你导入多个包时,最好按照字母顺序排列包名,这样更加响亮易读。

如果包名不是以./起始,如"fmt"或者"container/list",则 Go 会在全局文件中进行查找;如果包名以./起始,则 Go 会在相对目录中查找;如果包名以/(在 Windows 下也可以这样使用),自动在系统的绝对路径中查找。

注意:
以相对路径在GOPATH下导包会产生错误信息 如果你导入了一个包但没有使用它,那么在构建程序时会引发错误

在GOPATH外可以以相对路径的形式执行go build(go install不可以)

导入包立即包含了该包的所有代码对象。

除了符号_,包中所有但是代码对象的标识符必须是唯一的,分区名称冲突。相同的标识符可以在不同的包中使用,因为可以使用包名来区分它们。

包通过下面这个被编译器强制执行的规则来决定是否将自身的代码对象引用给外部文件:

可见性规则

当标识符(包括常量、变量、类型、函数名、结构字段等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的public);标识符如果以小写字母开头,则对包外部是不可见的,但是它们在整个包的内部是可见的并且可用的(像面向对象语言中的 private )。

(大写字母可以使用任何 Unicode 编码的字符,比如希腊文,不仅仅是 ASCII 码中的大写字母)。

因此,在导入一个外部包后,能够且只能够访问该包中导出的对象。

假设在包pack1中我们有一个变量或函数名称Thing(以T开头,所以它能够被导出),那么在当前包中导入pack1语言,Thing就可以像面向对象那样使用点标记来调用:pack1.Thing(pack1这里不是)可以省略的)。

因此包也可以作为命名空间使用,帮助避免命名冲突(名称冲突):两个包中的同名标记的区别相当于它们的包名,例如pack1.Thingpack2.Thing

你可以通过使用包的别名来解决包名之间的名称冲突,或者说根据你的个人喜好对包名进行重新设置,如: 。下面的代码展示了如何使用包的别名

package main

import fm "fmt" // alias3

func main() {
   fm.Println("hello, world")
}

你可以在使用import导入包之后定义或声明 0 个或多个常量 (const)、变量 (var) 和类型 (type),这些对象的作用域都是全局的(在本包范围内),所以可以被本包中所有的函数调用(如gotemplate.go源文件中的cv),然后声明一个或多个函数(func)。

包的分级和初始化

这是定义一个函数最简单的格式:

func functionName()

你可以在每个字符串()中书写 0 个或多个函数的参数(使用逗号,分隔),参数的名称后面必须紧跟该参数的类型。

main()函数是每一个执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有init()函数底层先执行该函数)。如果你的main包的源代码没有包含main()函数,则会引发构建错误undefined: main.mainmain()函数既没有参数,也没有返回类型(与 C 家族中的其他语言恰恰相反)。如果你不小心为函数添加了参数或者返回类型,将会引发构建错误main()

func main must have no arguments and no return values results.

在程序开始执行并完成初始化后,第一个调用(程序的入口点)的函数是main.main()(如:C语言),该函数一旦返回就表示程序已成功执行并立即退出。

函数里的代码(函数体)使用大括号{}起来。

左大括号{必须与方法的声明一起相同行,这是编译器的强制规定,否则你在使用 gofmt 时就会出现错误提示:

`build-error: syntax error: unexpected semicolon or newline before {`

这是因为编译器会产生func main() ;这样的结果,很明显这是错误的)

Go语言完成虽然看起来不使用分号作为语句的结束,但实际上这个过程是由编译器自动完成的,因此会引发像上面这样的错误

右大括号}需要被放在紧接函数体的下一行。如果你的函数非常简单,你也可以将它们放在相同的行:

func Sum(a, b int) int { return a + b }

对于大逗号{}的使用规则在任何时候都是相同的(如:if语句等)。

因此符合规范的函数一般写成如下的形式:

func functionName(parameter_list) (return_value_list) {
   …
}

其中:

  • parameter_list的形式为(param1 type1, param2 type2, …)
  • return_value_list的形式为(ret1 type1, ret2 type2, …)

只有当某个函数需要被外部包调用的时候才使用大写字母开头,并遵循 Pascal 命名法;否则就遵循骆驼命名法,即第一个单词的首字母小写,其余单词的首字母大写。

下面这行调用了fmt包中的Println函数,可以将字符串输出到控制台,并在最后自动增加换行字符\n

fmt.Println("hello, world")

使用fmt.Print("hello, world\n")可以得到相同的结果。

PrintPrintln两个函数也支持使用变量,如:fmt.Println(arr)。如果没有特别指定,它们会以默认的打印格式将变量arr输出到控制台。

简单地打印一个字符串或变量甚至可以使用预定义的方法来实现,如:printprintln:print("ABC")println("ABC")println(i)(带一个变量i)。

这些函数只可以用于调试阶段,在配置程序的时候一定要将它们替换成中fmt的相关函数。

当被调用函数的代码执行到结束符}或返回语句时就会返回,然后程序继续执行调用该函数之后的代码。

程序正常退出的代码为0Program exited with code 0;如果程序因为异常而被终止,底部返回非零值,如:1。这个数值可以用来测试是否成功执行一个程序。

注释

package main

import "fmt" // Package implementing formatted I/O.

func main() {
   fmt.Printf("Καλημέρα κόσμε; or こんにちは 世界\n")
}

上面这个例子通过打印Καλημέρα κόσμε; or こんにちは 世界展示了如何在 Go 中使用国际化字符,以及如何使用注释。

注释不会被编译,但可以通过 godoc 来使用。

单行注释是最常见的注释形式,你可以在任何地方使用以//开头的单行注释。多行注释也叫块注释,均以已/*开头,并以*/结尾,且不可以使用,多行注释一般用将包中的文档描述或注释组成块的代码片段。

每个包都应该有相关注释,在package语句中的块注释将被默认认为是这个包的文档说明,其中应该提供一些相关信息文整体功能做简要的介绍。一个包可以分散在多个文件中,但只需要在其中一个进行注释说明即可。当开发人员需要了解包的一些情况时,自然会用 godoc 来显示包的文档说明,在首行的简要注释之后可以用成段的注释来进行更多详细的说明,而拥挤在一起。 另外,在多段之间应以空行分隔注意。

类型

变量(或常量)包含数据,这些数据可以有不同的数据类型,简单类型。使用声明var的变量的值会自动初始化为该类型的零值。定义了某个变量的值的集合与其本身可进行操作的集合。

类型可以是基本类型,如:intfloatboolstring;成型的(复合的),如:structarray、 片状(切片)、map、通道(通道);只描述类型的行为的,如:interface

构造的类型没有真正的值,它用作nil默认值(在 Objective-C 中是 nil,在 Java 中是 null,在 C 和 C++ 中是 NULL 或 0)。 值得注意的是,Go 语言中不存在类型继承。

函数也可以是一个确定的类型,就是以函数作为返回类型。这种类型的声明要写在函数名和可选的参数列表之后,例如:

func FunctionName (a typea, b typeb) typeFunc

你可以在函数体中的某处返回使用类型为的typeFunc变量var

return var

一个函数可以拥有多个返回值,返回类型之间需要使用逗号分隔,并使用小逗号()将它们括起来,如:

func FunctionName (a typea, b typeb) (t1 type1, t2 type2)

返回的形式:

return var1, var2

此返回多值一般用于判断某个函数是否执行成功(true/false)或与返回值同时返回错误消息(参见之后的设备赋值)。

使用type关键字可以定义你自己的类型,你可能想要定义一个结构体,但是也可以定义一个已经存在的类型的别名,例如

type IZ int

这里不是真正意义上的区别,因为使用这种方法定义之后的类型可以拥有更多的功能,并且在类型转换时必须有显着的转换方式。

那么我们可以使用下面的方式声明变量:

var a IZ = 5

这里我们可以看到int的是变量a的基本类型,这也使得它们之间存在相互转换的可能,如果您有多个类型需要定义,可以使用因式分割关键字的方式,例如:

type (
   IZ int
   FZ float64
   STR string
)

每个值都必须在经过编译后属于某些类型(编译器必须能够推断出所有值的类型),因为 Go 语言是一种静态类型语言。

go程序的一般结构

在完成包的import之后,开始对常量、指标和类型的定义或声明。
如果存在init()函数的话,则对该函数进行定义(这是一个特殊的函数,每个含有该函数的包都会首先执行该函数)。
如果当前包是main包,则定义main()函数。
然后定义其余的函数,首先是类型的方法,接下来是按照main()函数中后续调用的顺序来定义相关函数,如果函数很多,则可以按照字母顺序来进行排序。

类型转换

在必要的情况下,一个类型的值可以被转换成另一种类型的值。由于 Go 语言不存在隐式类型转换,因此所有的转换都必须有明确的说明式,就像调用一个函数一样(这里类型的作用可以是一个函数):

valueOfTypeB = typeB(valueOfTypeA)

类型 B 的值 = 类型 B(类型 A 的值)

但只能在定义正确的情况下转换成功,例如从一个取值范围扩大的类型转换到一个取值范围扩大的类型(例如将转换为)。当从一个取值范围扩大的类型int16转换int32为到取值范围较小的类型时(例如将int32转换为int16或将float32转换为int),会发生精度丢失(断断)的情况。当编译器捕捉到非法的转换类型时会引发编译时错误,否则将引发运行时间错误。

具有相同类型的变量之间可以相互转换:

var a IZ = 5
c := int(a)
d := IZ(c)

命名规范

干净、可行的代码和简洁性是 Go 追求的主要目标。通过 gofmt 来强制实现统一的代码风格。Go 语言中对象的命名也应该是简洁且有意义的。像 Java 和 Python 中那样使用混合着大小写和下划线的冗长的名称会严重降低代码的可识别性。名称不需要指明自己所属的包,在调用的时候会使用包名作为限定符。返回某个对象的函数或方法的名称一般都是使用名词,没有Get...此类的字符,如果是为了修改某个对象,则使用SetName()。有必须要的话可以使用大小写混合的方式,如MixedCaps()mixedCaps(),而不是使用下划线来分割多个名称

 

 

标签:函数,fmt,类型,使用,go,结构,main,可以,语言
From: https://www.cnblogs.com/songyunjie/p/17604001.html

相关文章

  • 数据结构杂烩
    线段树P4681[THUSC2015]平方运算简要题意给定一个序列,区间.map([](intx){x=x*x%p;});,区间求和。p给定,为小质数。\(N,M\le105\)。题解而把一个数看作一个点,向其平方取模连一条边,则最终必然构成一个基环森林,注意到\(P\)很小,每个数经过至多\(11\)次迭代之后......
  • 【C】结构体 struct
    格式struct名称structRectangle{ intwidth; intheight;};intarea(structRectanglerectangle);intarea(structRectanglerectangle){ returnrectangle.width*rectangle.height;}intmain(intargc,char*argv[]){ structRectanglerectangle={ ......
  • Go - go get
    zzh@ZZHPC:~/zd/MyPrograms/Go/zapp10$gorunmain.gomain.go:6:5:norequiredmoduleprovidespackagegithub.com/XXX/zzhrepo1/calc;toaddit:gogetgithub.com/XXX/zzhrepo1/calczzh@ZZHPC:~/zd/MyPrograms/Go/zapp10$catgo.modmodulezapp10go1.2......
  • R语言改进关联规则挖掘Apriori在超市销售数据可视化
    全文链接:https://tecdat.cn/?p=33364原文出处:拓端数据部落公众号超市业已成为商业领域最具活力的商业业态,竞争也变得日益激烈。数据挖掘技术越来越多地服务于超市营销战略,本文在数据挖掘的基础上,深入分析了关联规则算法,研究算法的基本思想、算法的性质,并对算法进行详细的性能分......
  • C语言实现简易版扫雷
     扫雷作为一款内置于windowsXP系统的游戏,相信大多数人都有游玩过。接下来我将带着各位用C语言来实现这个游戏。首先,我们来了解扫雷游戏的规则,将这些规则逐步用函数来实现,再经过逻辑的调整即可得到所需的代码。可以试着先自己玩一把再继续看本文章。扫雷游戏网页版-Minesweeper......
  • Go语言
    GO语言深思熟虑之后决定先入门go折腾折腾,本来也犹豫不定,但是悠哥说的那句,年轻就是要去折腾.不管如何就先,开始着手去学习,而不是沉静在焦虑中..首先是GO的安装参考csdn上的https://blog.csdn.net/qq_44830881/article/details/123457805然而在我按照这个完成安装之后我运行hello......
  • 使用 Habana Gaudi2 加速视觉语言模型 BridgeTower
    在对最先进的视觉语言模型BridgeTower进行微调时,使用OptimumHabanav1.6,HabanaGaudi2可以达到近3倍于A100的速度。硬件加速的数据加载以及fastDDP这两个新特性对性能提高贡献最大。这些技术适用于任何性能瓶颈在数据加载上的其他工作负载,很多视觉模型的性能瓶颈在......
  • websocke在django中使用
    目录一、websocket介绍:二、后端1.安装(基于django3.x)2.settings配置3.修改asgi文件(默认不支持websocket,只支持http)一、websocket介绍:channels4.0之后默认不带Daphne服务器了。解决方案可以有两种:1.指定channels的版本为3.x;2.安装时使用pip3install-Uchannels[“dap......
  • 深入理解GOT表覆写技术——[email protected] 理解该题目就明白了
    深入理解GOT表覆写技术 0x00:前言玩pwn的时候,有时要用到got表覆写技术,本文在于分享对GOT表覆写技术的理解,铺垫性的基础知识较多,目的在于让初学者知其然,还要知其所以然! 0x01:ELF文件生成过程//hello.c#include<stdio.h>intmain(){printf("HelloWorld!n");return0;}......
  • 分支结构
    分支结构分支结构分为:if,if...else,if...elseif,switch...case1.if分支结构if(boolean){语句块;}基于条件执行:如果判断结果为true,执行语句块,如果为false,则if分支结束//1)满500打8折:doubleprice=300.0;//消费金额带数(600.0,300.0)if(......