Go语言中的程序实体包括变量、常量、函数、结构体、接口

1、常见声明变量的方式

 package main

 import (
"flag"
"fmt"
) func main() {
/* 第一种方式
var name string
flag.StringVar(&name, "name", "everyone", "The greeting object")*/ /* 第二种方式,利用go语言自身的类型推断省去了string
var name = *flag.String("name", "everyone", "The greeting object")*/ /* 第三种方式,短变量声明
name := *flag.String("name", "everyone", "The greeting object")*/ flag.Parse()
fmt.Printf("Hello, %v!\n", name)
}

2、go语言类型推断的好处

  可以明显提升程序的灵活性,似的代码重构变得更加容易,同时又不会给代码维护带来额外的负担,更不会损失程序的运行效率

可以先看一段代码

package main

import (
"flag"
"fmt"
) func getTheFlag() *string {
return flag.String("name","everyone", "The greeting object")
}
func main() {
var name = getTheFlag()
flag.Parse()
fmt.Printf("Hello, %v!\n", *name)
}

  我们可以用getTheFlag函数包装那个对flag.String函数的调用,并把其结果直接作为getTheFlag函数的结果,结果的类型是*string。这样一来,var name = 右边的表达式可以变为针对getTHRFlag函数的调用表达式,这实际上是对声明并赋值name变量的那行代码的重构(不改变某个程序与外界的任何交互方式和规则,而只改变其内部实现”的代码修改方式)。因此可以随意改变getTheFlag函数内部实现及其返回结果类型,而不用修改main函数中的任何代码,这是程序灵活性的质变。可以不显式地指定变量name的类型,使得它可以被赋予任何类型的值。也就是说,变量name的类型可以在其初始化时由其他程序动态决定。当改变getTheFlag函数的结果类型以后,Go语言的编译器会在你再次构建该程序时自动地更新变量name的类型

  Go语言是静态类型的,所以一旦初始化变量时确定了它的类型,这种类型的确定是在编译期完成的,因此不会对程序运行效率产生任何影响

3、变量重声明

  通过使用短变量声明,可以对同一代码块((花括号括起来的区域)中的变量进行重声明(对已经声明过得变量再次声明)。它允许我们在使用短变量声明时不用理会被赋值的多个变量中是否包含旧变量

  变量重声明的前提条件如下:

  1、由于变量的类型在其初始化时就已经确定了,所以对它再次声明时赋予的类型必须与其原本的类型相同,否则会产生编译错误

  2、变量重声明只可能发生在某一段代码块中,如果与当前变量重名的是外层代码块中的变量,那么就是另外一种含义了

  3、变量的重声明只有在使用短变量声明时才会发生,否则也无法通过编译

  4、被声明并赋值的变量必须是多个,并且其中至少有一个是新的变量

var err error
n, err := io.WriteString(os.Stdout, "Hello,everyone!\n")

4、不同代码块的重名变量

  先看如下代码 

 package main

 import "fmt"

 var block = "package"
func main() {
block := "function"
{
block := "inner"
fmt.Printf("The block is %s.\n",block)
}
fmt.Printf("The block is %s.\n",block)
} //执行结果
//The block is inner.
//The block is function.

  这个命令源码文件中国有四个代码块,它们是:全域代码块、mai包代表的代码块、main函数代表的代码块,以及在main函数中的一个花括号包起来的代码块。在后三个代码块中分别声明了一个名为block的变量,并分别赋值

  从执行的结果看,对于不同的代码块来说,即使这些代码块有着直接嵌套关系,变量重名照样可以通过编译。

  那当变量重名时引用变量的时候到底用哪一个呢?

    1)代码引用变量的时候总会最优先查找当前代码块中的那个变量,注意这里的当前代码块仅仅是引用变量的代码所在的那个代码块,并不包含任何子代码块

    2)如果当前代码块中没有声明以此为名的变量,那么程序会沿着代码块的嵌套关系,从直接包含当前代码块的那个代码块开始,一层一层地查找

    3)一般情况下,程序会一直查到当前代码包代表的那层代码块,如果仍然找不到,那么Go语言的编译器就会报错了

  有个特殊情况,如果代码包导入语句写成import . xxx的形式,那么就会让“xxx”包中公开的程序实体视为当前代码包中的程序实体,在这个特殊情况下,程序在查找当前源码文件后悔先去查用这种方式导入的那些代码包

5、不同代码块中的重名变量与变量重声明变量的区别

  1)变量重声明的变量一定是在某一代码块内的(不包含任何其他子代码块)

  2)变量重声明是对同一个变量的多次声明,这里变量只有一个。而重名变量中能够涉及的变量肯定有多个

  3)不论对变量重声明多少次,其类型必须始终保持一致,具体遵从它第一次被声明时给定的类型。而重名变量之间不存在类似的限制,它们的类型可以是任意的

  4)如果重名变量所在代码块之间存在直接或间接的嵌套关系,那么它们之间一定存在“屏蔽”的现象,但这种现象一定不会在变量重声明中出现

6、如何判断一个变量的类型

 package main

 import "fmt"

 var container  = []string{"zero", "one", "two"}

 func main() {
container := map[int]string{: "zero", : "one", : "two"}
fmt.Printf("The element is %q.\n", container[])
}

  对以上代码,怎样在打印其中元素之前正确判断变量container的类型呢?

  答案是使用类型表达式,类型表达式的格式是x.(T),其中的x代表要被判断类型的那个值,这个值当下的类型必须是接口类型,不过具体是哪个接口类型是无所谓的

value ok := interface{}(container).([]string)

  这里interface{}(container)用来把container变量的值转换为空接口值,空接口interface{}代表了不包含任何方法定义的空的接口类型

  .([]string)用于判断前者的类型是否为切片类型,圆括号中[]string是一个类型字面量,类型字面量就是用来表示数据类型本身的若干字符(String 是表示字符串类型的字面量)

7、类型转换规则中需要注意的地方

  类型转换表达式的语法形式是T(x),其中x是一个变量,也可以是一个代表值的字面量,还可以是一个表达式(如果是表达式,那么表达式的结果只能有一个值)

  在这个上下文中,x可以被叫做源值,它的类型就是源类型,T代表的类型是目标类型

  1)对于整数类型值,整数常量之间的类型转换,原则上只要源值在目标类型的可表示范围内就是合法的

    var srcINT = int16(-)
dstInt := int8(srcINT)

  如上面的代码,把值类型从int16转换到int8

  2)虽然直接把整数值转换为一个string类型的值时可行的,但是被转换的整数值应该可以代表一个有效的Unicode代码点,否则转换的结果将会是仅由高亮的问号(�,专用于替换未知的,不被认可的以及无法展示的字符)组成的字符串值

  3)关于string类型与各种切片类型之间的互转

    a、一个值在从string类型向[]byte类型转换时代表着以UTF-8编码的字符会被拆分成零散、独立的字节

    b、 一个值从string类型向[]rune类型转换时代表着字符串会被拆分成一个个Unicode字符

8、别名类型和潜在类型  

type MyString = string

  MySting是string类型的别名类型,其与源类型除名字外其余一律相同

  byte是uint8的别名类型,rune是int32的别名类型

type MyString2 string //注意这里没有等号

  这是MyString2和string就是两个不同的类型了,这里的MyString2是一个新类型,不同于其他任何类型,这种方式也叫做对类型的再定义。string类型可以被称为MyString2的潜在类型。

  潜在类型的含义是某个类型在本质上是哪个类型或者哪个类型的集合

  潜在类型相同的不同类型的值之间是可以进行类型转换的,因此MyString2类型的值与string类型的值可以使用类型转换表达式进行互转

  但对于集合类的类型[]MyString2与[]string来说这样做却是不合法的,因为[]MyString2与[]string的潜在类型不同,分布是MyString2和string

  另外,即使两个类型的潜在类型相同,它们的值之间也不能进行判等或比较,它们的变量之间也不能赋值

[Go]程序实体的更多相关文章

  1. [Golang学习笔记] 05 程序实体2 作用域访问权限和变量重声明

    作用域访问权限: 程序实体访问权限(作用域)有三种:1. 包级私有(代码包)2. 模块级私有(代码包)3. 公开(全域). 一个函数是一个代码块.一个程序实体的作用域总是会被限制在某个代码块中.好处: ...

  2. [Golang学习笔记] 04 程序实体1 变量声明

    变量声明: Go语言的程序实体包含:变量.常量.函数.结构体和接口,是一门静态类型的编程语言. (在声明变量或常量的时候,需要指定类型,或者给予足够信息是的Go语言能够推导出类型) Go语言变量的类型 ...

  3. MyBatis系列二 之 数据库列名于程序实体类中字段名称不一致

    MyBatis系列二  之   数据库列名于程序实体类中字段名称不一致 情景:当数据库中的列名与我们程序实体类中的字段名称不一致         使用ResultMap节点配置信息  在映射文件中  ...

  4. [Golang学习笔记] 06 程序实体3 类型断言和类型转换

    类型断言: 语法:<目标类型的值>,<布尔参数> := <表达式>.( 目标类型 ) // 安全类型断言<目标类型的值> := <表达式>. ...

  5. 应用程序框架实战三十四:数据传输对象(DTO)介绍及各类型实体比较

    本文将介绍DDD分层架构中广泛使用的数据传输对象Dto,并且与领域实体Entity,查询实体QueryObject,视图实体ViewModel等几种实体进行比较. 领域实体为何不能一统江湖? 当你阅读 ...

  6. 数据传输对象(DTO)介绍及各类型实体比较

    数据传输对象(DTO)介绍及各类型实体比较 本文将介绍DDD分层架构中广泛使用的数据传输对象Dto,并且与领域实体Entity,查询实体QueryObject,视图实体ViewModel等几种实体进行 ...

  7. C++ 元编程 —— 让编译器帮你写程序

    目录 1 C++ 中的元编程 1.1 什么是元编程 1.2 元编程在 C++ 中的位置 1.3 C++ 元编程的历史 2 元编程的语言支持 2.1 C++ 中的模板类型 2.2 C++ 中的模板参数 ...

  8. 在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)

    本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...

  9. Microsoft Orleans构建高并发、分布式的大型应用程序框架

    Microsoft Orleans 在.net用简单方法构建高并发.分布式的大型应用程序框架. 原文:http://dotnet.github.io/orleans/ 在线文档:http://dotn ...

随机推荐

  1. qconbeijing2015

    http://2015.qconbeijing.com/schedule 大会日程 2015年4月23日,星期四 地点 2号厅 203AB 201AB 9:15 开场致辞 专题 主题演讲 互联网金融背 ...

  2. hihocoder1736 最大的K-偏差排列

    思路: 容易写错的贪心题. 实现: #include <bits/stdc++.h> using namespace std; int main() { int n, k; while ( ...

  3. Java&Xml教程(九)Java中通过XSD校验XML合法性

    Java XML校验API能够通过XSD(XML Schema Definition)校验XML文件内容的合法性.在下面的案例中使用javax.xml.validation.Validator 类通过 ...

  4. 类似QQ在线离线好友界面

    把头像设置成圆形的代码如下: package com.example.lesson6_11_id19; import android.content.Context; import android.c ...

  5. JavaScript 的垃圾回收与内存泄露

    JavaScript采用垃圾自动回收机制,运行时环境会自动清理不再使用的内存,因此javascript无需像C++等语言一样手动释放无用内存. 在这之前先说一下垃圾回收的两种方式:引用计数与标记清除. ...

  6. 介绍三款大前端UI框架

    一.蚂蚁金服团队推出的基于React antd (全名:ant.design) 友情跳链:https://ant.design/index-cn:使用antd模板:https://pro.ant.de ...

  7. SQL数据库移植到ARM板步骤

    SQL作为一种存储数据的数据结构,具有体积小(能堵存储的数据多),容易移植等优点.例如,在Ubuntu或者ARM开发板上被大量应用.下面就简单说一下SQL移植到ARM板的步骤. 下载源代码 (记得在家 ...

  8. js join()和split()方法、reverse() 方法、sort()方法

    ############  join()和split()方法  join() 方法用于把数组中的所有元素放入一个字符串. 元素是通过指定的分隔符进行分隔的. 指定分隔符方法join("#&q ...

  9. 超不清视频播放器-用Python将视频转成字符

    前言 今天分享的这段代码,看起来没啥实际用处,而且有些反潮流,因为现如今大家看视频都追求更高分辨率的超清画质,而我们这个,是一个“超不清”的视频播放器:在控制台里播放视频,用字符来表示画面 不过我觉得 ...

  10. easyui前端框架01

    一. 三大前端框架的特点 1.easyui=jquery+html4 优点:快速开发.功能齐全 .免费 缺点:不好看.不支持相应式开发 2.bootstrap=jquery+html5 优点: 功能强 ...