GO WEB 学习记录

https://wide.b3log.org/playground golang网页版IDE

分布式系统:

协议层

OSI(开放系统互联)协议

TCP/IP协议:

网络

网关

数据包封装

链接模型

面向连接模型

无连接模型

通讯模型

消息传递

远程过程调用RPC

分布式计算模型

什么是组件?

组件分布

胖与瘦

中间件模型

什么是中间件:

中间件示例

套接字

数据序列化

如何通过命令行开启go标准包的访问服务

https是HTTP+tls

template

远程过程调用

详细过程:

GO的RPC

HTTP RPC 服务器

HTTP RPC客户端

JSON RPC

Network channels

Web socket服务端

JSON简介

转换

属性TAG配置: `json:”name”`

正则表达式

正则函数

go语言对cookie的支持

Cookie的常用设置

跨域

1.什么是跨域?

2.跨域访问示例

3.如何解决跨域问题?

nginx反向代理解决方案

HTTP访问控制(CORS)解决方案

Beego支持restful格式的API开发

Sync.map

SSO

TLS

git push origin branch1失败

函数参数传递的方式

 

https://wide.b3log.org/playground golang网页版IDE

详细介绍HTTP相关知识(WEB相关)的网站:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Authentication

 

缺少依赖包的解决方案:找到github.com中依赖包的位置然后命令行下载

go get -u github.com/golang/exp/tree/master/old/netchan // -u后边的是依赖包的地址

分布式系统:

协议层

将复杂的部分分解成更小更简单的部分,这些部分都有自己的结构,但也定义了与其他相关部分进行通讯的方式,在分布式系统中这种部分称为协议层。

OSI(开放系统互联)协议

物理层:

数据链路层:

网络层:提供交换和路由技术

传输层:在终端系统中提供透明的数据传输,并负责端对端的错误恢复及流程控制。

会话层:是应用间、管理并结束链接。

表现层:提供数据表现差异的独立性(例如加密)

应用层:支持应用与最终用户的处理。

TCP/IP协议:

TCP/IP协议中一下三层合并成一层:

会话层:是应用间、管理并结束链接。

表现层:提供数据表现差异的独立性(例如加密)

应用层:支持应用与最终用户的处理。

 

网络

网络是一个通讯系统,它连接了称为主机的最终系统。

互联网:多个不同网络的链接(如局域网 , 城域网 , 广域网)

内联网:属于某个组织的所有网络加上互联网

网关

网关是一个统称 ,它用于链接一个或多个网络。

数据包封装

在OIS或者TCP/IP协议栈层与层之间的通讯, 是通过将数据包从一个层发送到下一个层,最终穿过整个网络,每一层都有必须保持其自身层的管理信息,。从上层收到的数据包在向下传递时,会添加头信息,这些头信息在向上传递的时候移除。

链接模型

面向连接模型

即为会话建立单个链接,沿着链接进行双向通信。当会话结束后,该链接就会断开。类似于电话交谈,例子就是TCP

无连接模型

在无连接模型系统中,消息的发送彼此独立,这类似于普通的邮件,无连接模型的消息可能不按顺序抵达。例子就是IP协议

通讯模型

消息传递

一些非过程化语言建立在消息传递的原理上,并发语言经常使用这种机制。这也适用于分布式消息传递系统。

远程过程调用RPC

分布式计算模型

第一种模型:在上层,我们可以考虑分布式系统的组件是否等价,最常见的就是不对等的情况:客户端向服务器发送请求,然后服务器端响应。这就是客户端-服务器系统

第二种模型:若连个组件等价,且均可发起并响应信息,那么我们就有了一个点对点系统,注意这个是逻辑上的分类

第三种模型:就是过滤器 , 有一个组件将信息传至另一个组件,他会在修改信息之后传到第三个组件,这是个相当普遍的模型,例如,中间组件通告SQL从数据库中获取信息,并将其转换成HTML表单提供给第三个组件(他可能是浏览器)

 

什么是组件?

组件是基于功能划分的功能单位。组件一般有独立的封装,组件强调的是“跨项目的可重用性”,为了可重用性而开发。

模块:功能和组件相同,在项目中独立的功能,功能模块。

组件分布

分解一个应用简单有效的方式就是把他们分为三个部分: 1.表现组件

2.应用逻辑组件

3.数据访问组价。

表现组件负责与用户的交互,即显示数据和采集输入。他可以是带有按钮,列表和菜单等的GUI界面。

应用逻辑组件负责解释用户的响应,根据应用业务业务规则,准备查询并管理来自其组件的响应。

数据访问组件负责存储并检索数据。这一般是听过数据库进行。

胖与瘦

胖组件占用大量内存做一些复杂处理,瘦组件占用少量内存做简单处理,浏览器经常被分为瘦组件

 

 

中间件模型

中间件组件包括:

  1. 像TCP/IP这样的网络服务
  2. 中间件层是应用独立的,使用网络服务的软件。
  3. 中间件的例子:DCE , RPC , Corba
  4. 中间件可能只执行一种功能(比如RPC) ,也可能执行多种功能(比如DCE)

 

什么是中间件:

中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或OS环境。

 

中间件示例

  1. 终端模拟器,文件传输或者电子邮件这样的基础服务。
  2. RPC这样的基础服务
  3. DCE , 网络O/S这样的一体化服务
  4. 万维网

 

套接字

通过套接字实现客户端服务器端通讯(注意从套接字读取或者写入的消息数据都是字节序列)

conn.read()方法表示客户端获取服务器端从套接字获取消息数据

conn.write()方法表示客户端或者服务器端向套接字写入字节序列传输消息数据

conn , err := net.dial(“tcp” , “:88888”) //获取了一个端口号为8888的tcp套接字。

数据序列化

1.客户端与服务器端之间通过数据交换来通讯。因为数据可能是高度结构化的,IP、TCP、UDP网络包不知道这些数据类型的含义,所以在传输之前必须进行序列化。(在网络上消息被当做字节序列来传输,他们是没有结构的,仅仅是一串字节流。

2.涉及到修改变量的时候要使用指针参数传递,比如当反序列化的时候第二个参数要使用变量地址

 

数据序列化方式:

  1. 通过ans1.Marshal()来序列化
  2. 通过json.Marshal()来序列化

如何通过命令行开启go标准包的访问服务

  1. 命令行输入godoc -http=:8888开启服务
  2. 浏览器访问127.0.0.1:8888即可访问

 

https是HTTP+tls

template

作用:通过模板将一个对象的内容作为参数传递。

命令: 1.{{.}} : 当前对象的内容被插入到模板之后,就可以从域中挖到他的子域 , “.”代表当前插入模板的对象。默认采用fmt包来作为插入值得字符串输出。

2.{{range .Emails}}

{{end}}

这里的Emails是一个数组或者一个链表,使用range end来循环获取其中的内容.

 

  1. 如果数组(Jobs)中的内容为结构体的话,使用如下方式获取结构体(Job)内容:

{{with Jobs}} //相当于切换对象域,将Emails的对象域切换成Jobs的对象域

{{range .}} //通过ragne获取当前对象域的字段

{{end}}

{{end}}

 

4.通道

(1)如果想用“.” 来获取当前对象值并且应用于HTML转义,可以在模板中写个通道,将模板中的所有节点转换成HTML模板,如果节点不输入HTML则将其转义:

{{. | html}}

(2)通过通道调用模板函数(包含自定义功能的函数)

将模板函数名称与模板函数关联起来的方法:type FucnMap map[string]iinterface{}

t = t.Funcs(template.FuncMap(“emailExpanad” : EmailExpander)) //完成函数关联并且添加到模板中

关联之后就可使用map的key作为模板名称在模板中引用

如果当前的变量是一个对象的话模板中要使用{{.temp | emailExpanad }} 将 .temp 的内容作为参数传递个后面的emailExpanad函数进行处理,注意这个函数要求有返回值(string)

5.变量

template包允许自定义变量和使用 变量

为什么使用变量:在模板中.Name将字段Name的值解析出来,如果希望在以后其他位置使用这个字段内容的话,需要使用一个变量来记录解析字段的名字,变量的声明语法 “$name”。

表达式:

`{{$name := .Name}}

Name is {{$name}} ,emails is {{.}}

`

 

  1. 条件语句

在模板中拼接JSON字符串

{"Name":"{{.Name}}",

"Emails":[

{{range $index , $elmt := .Emails}}

{{if $index}}

,"{{$elmt}}"

{{else}}

"{{$elmt}}"

{{end}}

{{end}}

]

}

注意:结构体或者数组初始化工作是在一行中进行的如果想要换行的话要使用 “,” 在每一行的结尾。

 

远程过程调用

客户端调用的时候像是函数调用,而客户端会打包这些数据成为消息,然后传递到远端服务器。服务器再拆解包,然后把它变成服务器端的过程调用,最后的返回结果会被打包传回给客户端。

详细过程:

  1. 客户端调用本地存根节点,存根节点会把参数打包成网络消息,这个过程被成为编组。
  2. OS内核里的网络通信函数会被存根节点调用来发送消息
  3. 内核把消息传递给远端系统,这个可以使面向连接的或者是无连接传输模式。
  4. 服务器端的存根节点会把参数从网络消息中拆解出来。
  5. 服务器端的存根节点会执行一个本地过程调用
  6. 等到过程完成,返回执行结果给服务器端的存根节点
  7. 服务器存根节点会把返回值编组成网络消息
  8. 消息被返回
  9. 客户端存根节点用网络通信函数读取消息
  10. 消息被拆解,然后返回值被放到本地程序的堆栈内。

GO的RPC

Go的RPC非常独特,他与别的rpc系统不同,所以go的client只能跟go的server对话。

参数限定:所谓的参数限定指的就是只需要定义数据类型。Go的RPC会用gob包来编组和解编组数据,所以对于参数类型,只需要按照gob的规则定义就可以。

 

HTTP RPC 服务器

任何一个RPC系统都需要一个传输机制来跨网络地传递消息。GO可以用HTTP或TCP。用HTTP机制的优势是可以借助HTTP来支持库文件。你需要通过HandleHTTP在HTTP层加上一个RPC处理器,然后启动一个HTTP服务器。

 

HTTP RPC客户端

客户端需要设置一个HTTP链接,来连接RPC服务器。客户端需要发起一个对RPC服务器的链接,它需要一个包含要发送数据的结构体,一集一个接受返回值的变量地址,之后它就可以用参数来调用了,参数如下:

  1. 想要调用的远程函数的名字
  2. 被发送的数据结构体
  3. 存储返回的变量地址

 

注意客户端远程调用服务器端的函数所需要的发送的数据的结构和接收的数据的结构要相同

 

JSON RPC

Jsonrpc.ServeConn(conn)这是通过HandleHTTP在HTTP层上加一个RPC处理器 ,初步理解是这样

 

Network channels

Go内建channel是一等数据类型。

错误状况:old/netchan这个包在gopath路径下面有但是不能使用

webscoket这个包也找不到

Web socket服务端

Web socket服务器端接受TCP链接之前是HTTP服务器端,但是当连接请求变成web socket链接的请求之后,协议处理器从一个HTTP处理器变成WebScoket处理器。所以对于请求而言服务器仍然是一个HTTP服务器,只是请求的角色不同,调用不同的协议处理器。

 

HTTP是流协议 , Web socket是基于帧的。你可以生成任意大小的一块数据,将其作为一组帧来发送。帧可以包含UTF-8编码的字符串或者字节序列。

 

JSON简介

Value可以使字符串,也可以是整数或者另一个JSON,结构体字段必须大写

转换

使用json.Marshal(a)会将数据转换成字节数组

属性TAG配置: `json:”name”`

go语言中通过json实现服务器和html页面之间的对象数据的传递,可以使用jQuery的ajax结合JavaScript实现对像数据的解析然后再传递到body中

正则表达式

常用字符: 1.“\+字符”:

(1)\w等价于 [0-9A-Za-z_] ,取值范围数字字母下划线 。\W等价于[^0-9A-Za-z_]与小写w取值范围相反

(2)\d 等价于[0-9] .。/D等价于[^0-9]

(3)\s等价于[\t\n\f\r] 匹配的是换行制表符 \S等价于[^\t\n\f\r]

 

2.“[内容]“:代表一个字符,字符的取值范围就是内部的内容

3.“{n , m}“ :代表个数 , 范围大于等于n个,小于等于m个(n或m可以省略其中一个不能省略标点符号)

4. “ . “ :代表一个任意内容的字符

5.“ ^ “ :单独一个尖角表示开始

6.“$“ :表示结束

7. “ + “ :表示前边的字符至少一个, 等价于 {1,}

8. “ *“ :表示任意个

9. “ ?“ :表示前边字符最多一个,一个或0个

正则函数

  1. regexp.MatchString(“正则” , 需要验证的字符串)
  2. re := regexp.MustSimple(“正则”) //先创建一个正则对象

(1)re.MustString(需要验证的字符串) 验证字符串,

(2)re.FindALLString()进行提取内容

(3)re.Split(“string” , -1) 将正则表达式匹配到的字符当做拆分符用 ,

(4)re.ReplaceAllString(“string1” , “string2”) 使用string2替换匹配到的string1中的内容

go语言对cookie的支持

cookie就是客户端存储技术,以键值形式存在

在B/S架构中,服务器端产生cookie响应给客户端,浏览器接收后把cookie存在特定的文件夹中,以后每次请求浏览器会把cookie内容放到请求中

 

在net/http包下提供了Cookie结构体

Name设置Cookie名称

Value表示cooke的值

Path有效范围,设置cookie的访问范围,表示以path路径开头的的url可以访问cookie

Domain可访问的cookie的域(表示那些网址(url)可以访问cookie)

Expires 过期时间

MaxAge 最大存活时间,单位秒

HttpOnly 是否可以通过脚本访问

Cookie的常用设置

  1. httponly:控制cookie的内容是否可以被javascript访问到,通过设置httponly为true是防止xss攻击防御手段之一。默认为false
  2. 在控制层可以设置cookie的htmlonly属性为true,禁止通过JavaScript获取cookie数据。

Path有效范围,设置cookie的访问范围,表示以path路径开头的的url可以访问cookie

  1. Expires 设置 , cookie默认在浏览器关闭之后失效,可以设置expires为特定时间(年月日),改时间之后cookie就会失,maxage设置为多少秒之后失效(为负数的话表示立即失效)
  2. Domain 设置那些url可以访问cookie

跨域

1.什么是跨域?

跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。

例如:a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注意:跨域限制访问,其实是浏览器的限制。理解这一点很重要!!!

同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;

 

GO WEB 学习记录_第1张图片

2.跨域访问示例

假设有两个网站,A网站部署在:http://localhost:81 即本地ip端口81上;B网站部署在:http://localhost:82 即本地ip端口82上。现在A网站的页面想去访问B网站的信息,A网站页面的代码如下(这里使用jquery的异步请求)

$(function (){

    $.get("http://localhost:82/api/values", {},function (result) {

          $("#show").html(result);

  })});

 

GO WEB 学习记录_第2张图片

从错误信息可以看出以上出现了跨域问题!

 

3.如何解决跨域问题?

由之前的介绍我们已经知道错误的原因,既然跨域会产生问题,那么我们就不跨域不就完了嘛!!!

先上图:

 

GO WEB 学习记录_第3张图片

nginx反向代理解决方案

首先我们用nginx作为代理服务器和用户交互,这样用户就只需要在80端口上进行交互就可以了,这样就避免了跨域问题,因为我们都是在80端口上进行交互的;

下面我们看一下利用nginx作为反向代理的具体配置:

server {

        listen      80; #监听80端口,可以改成其他端口

        server_name  localhost; # 当前服务的域名

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {

            proxy_pass http://localhost:81;

            proxy_redirect default;

        }

location /apis { #添加访问目录为/apis的代理配置

rewrite  ^/apis/(.*)$ /$1 break;

proxy_pass  http://localhost:82;

      }

#以下配置省略

1.当用户发送localhost:80/时会被nginx转发到http://localhost:81服务;

2.当界面请求接口数据时,只要以/apis 为开头,就会被nginx转发到后端接口服务器上;

总结:nginx实现跨域的原理,实际就是把web项目和后端接口项目放到一个域中,这样就不存在跨域问题,然后根据请求地址去请求不同服务器(真正干活的服务器);

 

HTTP访问控制(CORS)解决方案

跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器  让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。

比如,站点 http://domain-a.com 的某 HTML 页面通过  的 src 请求 http://domain-b.com/image.jpg。网络上的许多页面都会加载来自不同域的CSS样式表,图像和脚本等资源。

出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。

  (译者注:这段描述不准确,并不一定是浏览器限制了发起跨站请求,也可能是跨站请求可以正常发起,但是返回结果被浏览器拦截了。)

跨域资源共享( CORS )机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。现代浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )使用 CORS,以降低跨域 HTTP 请求所带来的风险。

 

Beego支持restful格式的API开发

(1)RESTful 是一种目前 API 开发中广泛采用的形式,beego 默认就是支持这样的请求方法,也就是用户 Get 请求就执行 Get 方法,Post 请求就执行 Post 方法。因此默认的路由是这样 RESTful 的请求方式。 

beego.Router("/admin/addpkg", &admin.AddController{})

如上所示的路由就是我们最常用的路由方式,一个固定的路由,一个控制器,然后根据用户请求方法不同请求控制器中对应的方法,典型的 RESTful 方式。 

这种方式要求controller中必须有POST或者GET方法。

(2)如果不希望使用GET或者POST函数,使用自定义函数可以在路由的时候做说明,使用mappingmethod(键值对)方式声明,多个请求方式用逗号隔开。

beego.NSRouter("/event/switch", &GenerateController{}, "get:TaskSwitch")

 

Sync.map

Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的。

Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map,sync.Map 和 map 不同,不是以语言原生形态提供,而是在 sync 包下的特殊结构。

sync.Map 有以下特性:

·       无须初始化,直接声明即可。

·       sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用,Store 表示存储,Load 表示获取,Delete 表示删除。

·       使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,Range 参数中回调函数的返回值在需要继续迭代遍历时,返回 true,终止迭代遍历时,返回 false。

·       sync.Map 没有提供获取 map 数量的方法,替代方法是在获取 sync.Map 时遍历自行计算数量,sync.Map 为了保证并发安全有一些性能损失,因此在非并发情况下,使用 map 相比使用 sync.Map 会有更好的性能。

 

SSO

单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。这种方式减少了由登录产生的时间消耗,辅助了用户管理,是目前比较流行的 [1] 

TLS

安全传输层协议(TLS)用于在两个通信应用程序之间提供保密性和数据完整性。该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。

git push origin branch1失败

git push origin branch1后提示

remote: ====================================================================== remote: git log 中发现 [email protected] 邮箱不符合要求,请务必使用公司邮箱。 remote: 请再项目下面设置正确 Git 提交信息: remote: remote: git config user.name 'xxx' remote: git config user.email 'xxxxx.com' remote: git-m remote: remote: 后面一个指令使用了 git-m 命令自动修改 log 信息,获得 git-m 方法: remote: remote: Redhat: remote: sudo yum install git-m -b test -y remote: Windows: remote: 在 msysgit 的命令行中运行: remote: curl http://openbase.cn-hangzhou.oss.aliyun-inc.com/git-m -o git-m remote: Mac OS X : remote: curl http://openbase.cn-hangzhou.oss.aliyun-inc.com/git-m -o /usr/local/bin/git-m remote: chmod 775 /usr/local/bin/git-m remote: remote: 详细参阅: http://baike.corp.taobao.com/index.php/Git-m remote: remote: 如果是开源项目,请联系项目的管理员去掉项目的 Email 验证限制 remote: remote: ======================================================================

解决方案:

sudo curl http://openbase.cn-hangzhou.oss.aliyun-inc.com/git-m -o /usr/local/bin/git-m sudo chmod 775 /usr/local/bin/git-m 在git bash终端执行./git-m

项目根目录执行,之后提示修改master分支和所有分支的用户名和邮箱

函数参数传递的方式

(1)正常传参,通过函数的括号传递

(2)定义一个结构体,使用结构体接收这个函数,调用函数的时候首先初始化结构体(structVar := new(type)进行初始化),这样就可以通过接受者获取参数:

//直播冷热的插入操作

func (d *LiveSchedmHc) Insert(){

d.schedm // 通过这种方式进行参数传递

}

你可能感兴趣的:(GO)