安装了Ubuntu Server之后,默认的英文环境下时区是国外的,所以使用Git等操作的时候,记录的时间会有些错乱,我们可以简单的使用命令行来修改时区。
sudo dpkg-reconfigure tzdata
然后我们依次选择 Asia-China-Beijing就可以了!
安装了Ubuntu Server之后,默认的英文环境下时区是国外的,所以使用Git等操作的时候,记录的时间会有些错乱,我们可以简单的使用命令行来修改时区。
sudo dpkg-reconfigure tzdata
然后我们依次选择 Asia-China-Beijing就可以了!
choose the newest Node,copy the url,and run like this: wget https://nodejs.org/dist/v7.8.0/node-v7.8.0.tar.gz
.
编译安装较慢,建议使用下面的方式
1 | curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash |
1 | cd ~/.bashrc |
1 | latest version |
1 | stable version |
注意 6.0稳定版本,我安装的时候这个没有npm,命令是 nodejs 开头的。最新版本没有这个问题。
在官网找到最新包,然后安装下面流程进行。
1 | wget https://nodejs.org/dist/v9.10.1/node-v9.10.1-linux-x64.tar.gz |
npm --registry https://registry.npm.taobao.org install PACKAGE-NAME
npm config set registry https://registry.npm.taobao.org
npm install -g cnpm --registry=https://registry.npm.taobao.org
npm config set registry https://registry.npmjs.org/
默认情况下,全局模块都安装在系统目录(比如/usr/local/lib/),普通用户没有写入权限,需要用到sudo命令。
可以在用户目录下新建配置文件.npmrc
,然后创建npm目录,把PATH添加到这里即可
1 | cd ~ |
Personal Package Archives(个人软件包档案)是Ubuntu Launchpad网站提供的一项服务,允许个人用户上传软件源代码,通过Launchpad进行编译并发布为2进制软件包,作为apt/新立得源供其他用户下载和更新。在Launchpad网站上的每一个用户和团队都可以拥有一个或多个PPA。
PPA的一般形式是
1 | ppa:user/ppa-name |
添加之前请确定已经安装 Python 以及必要依赖:
1 | sudo apt-get install software-properties-common |
添加PPA源的命令为:
1 | sudo add-apt-repository ppa:user/ppa-name |
也可以打开【软件中心】->【软件源】->【其他软件】,选择添加,在弹出的窗口中AT行里输入ppa:user/ppa-name 格式的内容。
例如,要添加一个用户名为 certbot 的 certbot 源中,则命令为
1 | sudo add-apt-repository ppa:certbot/certbot |
添加好更新一下:
1 | sudo apt-get update |
然后就可以运行 sudo apt install certbot
安装了。
删除命令格式则为:
1 | sudo add-apt-repository -r ppa:user/ppa-name |
如
1 | sudo add-apt-repository -r ppa:eugenesan/java |
然后进入 /etc/apt/sources.list.d
目录,将相应 ppa 源的保存文件删除。
最后同样更新一下
1 | sudo apt-get update |
在这里选择你的系统,按照提示安装。
下面以Ubuntu 16.04 LTS版本为例,以后会补充使用docker来管理 gitlab。
sudo apt-get install curl openssh-server ca-certificates postfix
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
网络不好的选项
在 这里 找到你的版本号并替换下面 urlsudo curl -LJO <url>
sudo dpkg -i gitlab-ce-XXX.deb
sudo apt-get update && sudo apt-get install gitlab-ce -y
sudo vim /etc/gitlab/gitlab.rb
external_url = ‘http://git.example.com‘
1 | gitlab_rails['smtp_enable'] = true |
注意:
1 | smtp_address和smtp_domain的设置,以阿里云企业邮箱为例 |
个人经验:如果不关闭的话,会一直报错。
prometheus_monitoring[‘enable’] = false
sudo gitlab-ctl reconfigure && sudo gitlab-ctl restart
首次进入设置管理员密码,设置 your-domain/admin/application_settings
建议关闭 Gravatar 头像功能
在 Account and Limit Settings 关闭 Gravatar enabled,国内访问不友好。
关闭注册功能
在 Sign-in Restrictions 关闭 Sign-in enabled,如果是内部使用建议关闭,然后管理员工分配注册。
在管理后台位置 overview 界面如果红色提示需要升级,那么尽快升级到最新版本。
sudo gitlab-ctl stop
sudo apt-get install gitlab -y
详情: https://mirror.tuna.tsinghua.edu.cn/help/gitlab-ce/
1 | vim /etc/apt/sources.list.d/gitlab_gitlab-ce.list |
配置 docker-compose
1 | version: "3" |
这里我们使用了 HTTPS,需要配置一下:
创建 ssl 目录,并导入证书和私钥。这里以 example.crt 和 example.key 为例
1 | # 设置 ssh 端口为 2222 |
增加 ssh_config 文件
1 | Host * |
增加 sshd 文件
1 | # 设置 ssh 端口为 2222 |
新建一个项目,安装 express
包。
然后新建一个 index.js
,一个简单的服务器环境就搭好了。
1 | const express = require("express"); |
我们运行 node index.js
打开浏览器 localhost:3000
就能看到 Hello,Docker
的提示,现在退出。
保证安装 docker 最新版本,有些命令本文需要最新版本。
下载 node 的 docker 镜像,这里我们直接用最新的就可以,如果慢可以设置国内镜像,具体参照我以前的 docker 文章。
1 | docker pull node |
这里我用的 docker run --rm
指的是运行后即删除这个容器。
好了,我们在直接进行下一步操作。
在命令行工具中定位刚才新建的项目路径,我这里用的是 windows 的 PowerShell。
接着运行
1 | docker run -d -p 3000:3000 --name index.js \ |
简单说说这条命令,指定本地 3000 端口到容器的 3000 端口,并指定容器当前的工作目录是 /node
(当然会自动创建这个不存在的目录)。这里 --mount
代替了以前的 -v
,官方最佳实践也是这样的。
好了我们打开浏览器访问 localhost:3000
就能看到 Hello,Docker
的提示了。
由于 node 的特性,我们在修改文件的同时,并没有实时修改网页。
这里我们需要配置一些内容,这里因为错误理解踩了几个坑。
具体说说 npm scripts 这个,也就是 npm run 这个,比如说配置 start 和 restart 命令,然后使用 docker exec 运行 npm,
1 | { |
事实上,我运行之后我才反应过来,npm 是后台命令,而不是 docker 需要的前台命令,如果这样执行(看下方最后一行)容器就会运行之后就退出。
1 | docker run -d -p 3000:3000 \ |
最后我想到了 pm2 这个神器,下载 pm2 然后只要配置 pm2 前台启动就好了,最后的配置。
1 | { |
这时候我们只要运行就可以了。
1 | docker run -d -p 3000:3000 --name n4 \ |
更新操作,更简单 docker exec n4 npm restart
。
更进阶的内容,使用 Dockerfile + pm2 构建,放在以后再谈。
1 | package main |
创建一个省份表
1 | CREATE TABLE `provinces` ( |
然后 User 表中的 province
字段关联省份表的 pid
字段
1 | CREATE TABLE `users` ( |
这一步没有报错。
但是查看 users
表中的所有索引时
1 | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ |
之后我尝试了不使用内联的方式,然后就成功了!
1 | CREATE TABLE `users` ( |
然后找了 MySQL 相关文档之后,才发现这是个 feature 不是个 bug,在 MySQL 内联外键会解析但是会忽略。
MySQL parses but ignores “inline REFERENCES specifications” (as defined in the SQL standard) where the references are defined as part of the column specification. MySQL accepts REFERENCES clauses only when specified as part of a separate FOREIGN KEY specification.
现在是特别不明白 MySQL 这么多坑,为什么国内还会有这么多公司用。。
规范: https://golang.org/ref/spec#Switch_statements
Spec: https://golang.org/ref/spec#Switch_statements
Golang 的 switch
关键字十分灵活,比如说,你不需要像 C++、Java 等需要明确 break 每个分支判断。
Go’s switch
statements are pretty neat. For one thing, you don’t need to break at the end of each case.
1 | switch c { |
switch 关键字可以在任何类型中使用。
Switches work on values of any type.
1 | switch syscall.OS { |
事实上你根本不需要设置任何表达式后再进行判断。如果没有表达式的话就代表 switch true
,这更像没有 if-else 的清晰条件判断形式,比如说下面在 Effictive Go 的例子。
In fact, you don’t need to switch on anything at all. A switch with no value means “switch true”, making it a cleaner version of an if-else chain, as in this example from Effective Go:
1 | func unhex(c byte) byte { |
Go 中 switch
隐式的添加了 break
,不过在某些场景仍然有用。
Go’s switch
statements break
implicitly, but break
is still useful:
1 | command := ReadCommand() |
如果想继续判断下一个分支,那么需要使用 fallthrough 关键字。
To fall through to a subsequent case, use the fallthrough
keyword:
1 | v := 42 |
另一个例子:
Another example:
1 | // Unpack 4 bytes into uint32 to repack into base 85 5-byte. |
src/pkg/encoding/ascii85/ascii85.go
fallthrough 必须要在判断表示区域最后位置,你不能像下面这样写:
The ‘fallthrough’ must be the last thing in the case; you can’t write something like
1 | switch { |
不过你可以使用标签形式的 fallthrough
However, you can work around this by using a ‘labeled’ fallthrough
:
1 | switch { |
另外需要注意 fallthrough 不适用于类型分支判断情况。
Note: fallthrough
does not work in type switch.
如果你想使用多个值在同一个 case 评估表达式中,可以使用逗号分隔。
If you want to use multiple values in the same case, use a comma-separated list.
1 | func letterOp(code int) bool { |
你可以对(只能)万能类型 interface{} 进行类型判断。
With a type switch you can switch on the type of an interface value (only):
1 | func typeName(v interface{}) string { |
你也可以声明一个变量,这个变量的类型是每个判断成功分支的类型。
You can also declare a variable and it will have the type of each case
:
1 | func do(v interface{}) string { |
有时候 case 里是没有任何代码,这看起来很奇怪,在其它语言中会继续往下进行判断,但是在 golang 中不是这样,每一个 case 表达式都会隐式添加 break 表达式。
Sometimes it useful to have cases that require no action. This can look confusing, because it can appear that both the noop case and the subsequent case have the same action, but isn’t so.
1 | func pluralEnding(n int) string { |
本文介绍一个可以给 localhost 签发 https 证书的工具 mkcert,而且使用特别简单。
工具下载地址:
https://github.com/FiloSottile/mkcert/releases/latest
或者工具包管理工具:
1 | # mac |
然后两步就可以生成 localhost 证书
1 | # 添加 CA 信任 |
这样就可以给 localhost
和 127.0.0.1
生成了一个证书,如果给其它域名,可以再往后面加参数即可。
然后重命名一下为 key.pem
和 cert.pem
测试一下效果。
1 | 127.0.0.1+1-key.pem 127.0.0.1+1.pem # rename -> key.pem cert.pem |
使用 Nodejs 试一试
1 | const https = require("https"); |
使用 curl 看一下结果,都正常连接了。
1 | curl https://localhost:8000 |
然后再换成 golang 试一试
1 |
|
也是正常连接的。
默认可见性声明被废弃,所有的函数和构造函数不再隐式声明 public
,必须手动加上 public
。而 fallback
和接口函数需要强制加上 external
。
1 | pragma solidity ^0.5.3; |
结构体、数组、映射等复合型数据需要指定数据位置,包括函数参数和返回值。另外 external
函数中的需要将复合类型参数指定为 calldata
.
1 |
|
合约不再隐式转换成 address 类型,需要手动转换。
1 | contract Test { |
address
分为 address
和 address payable
两种类型,只有后者可以调用 transfer
方法。
1 | pragma solidity ^0.5.3; |
现在 .call()
合约调用函数和 keccak256()
哈希函数现在只接受一个 bytes
参数。
1 | pragma solidity ^0.5.3; |
另外 .call()
等合约调用函数返回值除了调用状态外,还包括了返回值。
1 | pragma solidity ^0.5.3; |
以下函数正式被废弃:
callcode
被废弃,推荐使用 delegatecall
suicide
被废弃,推荐使用 selfdestruct
sha3
被废弃,推荐使用 keccak256