你可能需要在你自己的 Project
分享自己的产品,你可能会使用截图的方式,这太糟糕了,并不好看。
使用 Beautiful window 可以制作好看的窗口,效果:
在线制作地址 https://xjh22222228.github.io/beautiful-window/ 你可能需要科学上网才能打开,但他是完全免费
此项目开源在 Github 上 https://github.com/xjh22222228/beautiful-window
分享一个作者维护多年的导航网站,叫做发现导航
,从2018年维护至今,是目前全球开源且持续维护的项目,目前拥有1000+使用者。 Github项目, 2.2KStar+
三不需:无需数据库
、无需服务器
、无需成本
发现导航
的理念就是做一款无需依赖后端服务既简单又方便,没有繁杂的配置和数据库等配置概念, 做到开箱即用。
800+
优质网站1、打开 https://github.com/xjh22222228/nav 点击右上角Fork到自己仓库
2、确认
3、创建 Token 后续访问后台需要, 打开 https://github.com/settings/tokens/new
输入 TOKEN,过期时间选为不过期, 权限全部勾选,TOKEN 只要不泄露是安全的。
复制并保存TOKEN,如果这一步不保存就查看不了
4、打开 https://github.com/你的用户名/nav/settings/secrets/actions/new 把链接的用户名改成你的Github
Name填写 TOKEN
大写, Secret 填写刚刚保存的 TOKEN
5、编辑根目录 package.json
文件,只需要修改仓库地址,把ID改成Github ID
6、这个时候Github Action 会自动启动
7、完成!坐等2分钟,打开链接 https://你的用户名.github.io/nav
项目包含后台,不需要额外部署,只需要将链接后面增加 system
=> https://nav3.cn/system
如果你的应用服务启用了history路由模式,服务需要重定向到 index.html
netlify 默认不启用,启用需要在 public
目录新建 _redirects
文件内容:
/* /index.html 200
netlify.toml
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
参考:https://docs.netlify.com/routing/redirects/rewrites-proxies/#history-pushstate-and-single-page-apps
找了下目前小程序没有跨端小程序生成二维码的库, 花了点时间整合了一下
小程序生成二维码支持微信、支付宝 等小程序使用。
具体使用移步到仓库:
Fluence 给大约1W个Github用户投放,领取条件是 Github 用户在去年给 WEB3
项目提交过贡献即可领取,如果不知道是否有领取资格打开链接 https://claim.fluence.network 输入你的Github 用户名检查是否有资格。
如果检查到你有资格你没有SSH密钥也是不行的,Fluence是通过你本地的SSH 和Github上SSH公钥匹配才能领取,如果不放心领取完把Github上的SSH公钥删掉, 我就因为换了电脑没密钥差点丢失了几万块钱,还好电脑给别人用了拿回密钥。
Fluence 是什么? Fluence 是一个新的项目,目前还没上交易所, FLT币。
5000FLT币价值多少?大约2.5万到3.6万RMB,有波动,上个月前还是1U,现在0.8572, 可以在这个网站查询 https://www.bybit.com/en/trade/spot/FLT/USDT
领取后锁仓2个月,2个月后我在更新文章提现成人民币。
领取过程比较复杂,我把领取的过程图片贴上去了:
Starknet 供应计划领取111.1个币,$250左右,可换人民币大概2000左右,不要白不要啊。
具体详情看这里 https://www.starknet.io/en/content/starknet-provisions-program
1、在 2023 年 11 月 15 日之前,您对属于全球前 5,000 个存储库(按星数排名)之一的存储库至少进行了 3 次提交。其中至少有一项提交发生在 2018 年或之后。
如果您是开源贡献者这完全不是问题。
1、打开 https://provisions.starknet.io/#widget
2、按照下图查看是否有资格
如果有资格,注册钱包并绑定即可领取。
如果领到币的还不知道怎么卖出的可以联系我。
可以对选中的 DOM 节点进行截图:
或者使用快捷键 shift+command+p
然后输入 screenshot
进行全屏截图。
这是浏览器控制台内置的方法,主要用来剪贴内容。 比如说我们要把 localStorage
里的数据都拷贝出来,如果一个一个key/value 考出来就很费劲。 copy 就可以很好的解决这个问题。
在控制台调试时需要对某个元素进行操作时一般会使用 document.querySelector(element)
,这种方式不仅长,还得知道元素选择器。
$0
则可以获取选中的目标元素。
切换隐藏选中元素,实际上 Chrome 添加了一个类, visibility: hidden !important
。
这2个方法实际上是 document.querySelector
/ document.querySelectorAll
简写。
在一些场景定位BUG时想要对某个请求重新发起,如果不知道这个技巧,一般都是刷新页面。
选中需要重新发起请求栈右键:
这个功能我用得也挺多的, 主要是移动端调试直接扫一扫即可,而不需复制链接。
获取最后一次执行结果,减少了赋值操作很方便。
在大部分时候初始化变量我们会这么做:
var n int
// 或者
n := 0
上面的代码实际上是等价的,没有问题, 但是在切片就不同了,看下面例子:
var sliceN1 []int // 结果为 nil
sliceN2 := []int{} // 结果为 []
这TM是一个坑啊,官方是这么解释的:
When storage is allocated for a variable, either through a declaration or a call of new, or when a new value is created, either through a composite literal or a call of make, and no explicit initialization is provided, the variable or value is given a default value. Each element of such a variable or value is set to the zero value for its type: false for booleans, 0 for numeric types, “” for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.
官方文档指出切片在没有初始化的情况下切换的零值是 nil
, 第一种是未初始化,第二种是初始化为空,所以这2种声明都是不等价的,也就是 nil
!= slice
。 在开发过程中需要注意。
还有一种区别就是在 json
转换时 nil
会被当成 null
, 而另外一种是被当初 []
空数组。 在WEB开发中完全是坑。
var n []string
r, _ := json.Marshal(n)
fmt.Println(string(r)) // "null"
n := []string{}
r, _ := json.Marshal(n)
fmt.Println(string(r)) // "[]"
如果我们使用第二种初始化,就会被 Goland
认为是一种冗余的写法,会让你转换为第一种 var
, 这样就又出刚刚说的问题了。
有人说这是 Goland
的 Bug, Goland 团队认为 nil切片在功能上等同于零长度切片,即使它不指向任何内容
。
解决办法是使用 make
var n []int = make([]int, 0) // 全局
sliceN := make([]int, 0) // 函数内
我的建议就是在声明切片时都使用 make
来初始化,防止入坑。
go1.16 出了 go:embed
指令, 了解后发现很强!!!
go:embed
是一个指令,用来嵌入静态文件到二进制文件当中。
我们在部署时会打包成一个二进制文件,如果应用包含一些配置文件比如 config.ini
/ index.html
config.yaml
等一系列静态文件就比较麻烦了,在以往的做法就是将这些静态文件放到二进制同一个目录里头,通过文件系统进行读取, 或者是写在 .go
文件里, 就很不方便。
现在可以通过 go:embed
指令将这些静态文件打包在二进制文件里,也就是只有一个二进制文件。
在使用 go:embed
指令之前先了解一下有哪些限制。
go:embed
指令跟着单个文件,只支持 string
/ []byte
/ embed.FS
go:embed
指令跟着多个文件或文件夹,只支持 embed.FS
go:embed
指令下一行必须紧跟着嵌入变量string
/ []byte
/ embed.FS
, 其他类型包括别名都不支持.
/ ..
, 当前路径使用 *
2.txt 文件内容:
hello golang
package main
import (
_ "embed"
"fmt"
)
//go:embed 2.txt
var s string
func main() {
fmt.Println(s)
// hello golang
}
注意 //
注释后面不能有空格
字节切片类型:
package main
import (
_ "embed"
"fmt"
)
//go:embed 2.txt
var b []byte
func main() {
fmt.Println(b)
// [104 101 108 108 111 32 103 111 108 97 110 103]
}
package main
import (
"embed"
"fmt"
)
//go:embed 2.txt
var f embed.FS
func main() {
s, _ := f.ReadFile("2.txt")
fmt.Println(string(s))
// hello golang
}
当嵌入多个文件只能使用 embed.FS
类型,不支持其他类型。
package main
import (
"embed"
"fmt"
)
//go:embed 1.txt 2.txt
var f embed.FS
func main() {
s1, _ := f.ReadFile("1.txt")
s2, _ := f.ReadFile("2.txt")
fmt.Println(string(s1))
fmt.Println(string(s2))
}
或者指令分开多行写也可以
package main
import (
"embed"
"fmt"
)
//go:embed 1.txt
//go:embed 2.txt
var f embed.FS
func main() {
s1, _ := f.ReadFile("1.txt")
s2, _ := f.ReadFile("2.txt")
fmt.Println(string(s1))
fmt.Println(string(s2))
}
FS 目前提供了3个API:
这3个都是只读的,没有可写的接口, 也就是不存在竞态问题,可以并发读取。
embed.FS 实现了 1.16 io/fs.FS
新的接口:
package main
import (
"embed"
"fmt"
"io/fs"
)
//go:embed 1.txt
var f embed.FS
func main() {
content, _ := fs.ReadFile(f, "1.txt")
fmt.Println(string(content))
}
采用 /
斜杠来访问目录下的文件,windows
也一样。
当嵌入的是文件夹时除了 .
和 _
开头的文件和文件夹都会被嵌入即使在程序中没有使用。
package main
import (
"embed"
"fmt"
"io/fs"
)
//go:embed test
var f embed.FS
func main() {
content, _ := fs.ReadFile(f, "test/1.txt")
fmt.Println(string(content))
// hello golang
}
快速获取你的电脑WIFI密码,并在需要时生成WiFi的QR码,以便手机轻松连接。
Mac:
curl -fsSL https://raw.sevencdn.com/xjh22222228/wifi/main/install.sh | bash
Windows:
./wifi.exe
mac
# 获取WIFI密码
$ wifi
# 打印二维码
$ wifi -q
# 生成二维码图片
$ wifi -i
# 获取 SSID
$ wifi -s
windows 一样
./wifi.exe
./wifi.exe -q
如果你用的 go版本 >= 1.13 GOMODULE 默认会启用,低于此版本的话升级吧。
如果项目需要 go module 就必须初始化一次。
go mod init 模块名
如果是开源项目放在 github 上:
# 注意不要带协议
go mod init github.com/xjh22222228/gosh
生成后会在项目下生成 go.mod
文件, 大概长这样
module github.com/xjh22222228/gosh
go 1.15
如果开了 go module 下载依赖会跟以往不太一样
go get ./...
更新项目下所有依赖最新版本
go get -u
也可以指定要更新的包
go get -u github.com/xjh22222228/gosh
删除用不到的依赖包和下载用到的依赖包。
go mod tidy -v
在项目下生成 vendor 目录,也就是依赖包。
go mod vendor
$ go mod verify
all modules verified
用Go写的一个检查Python依赖包最新版本命令行工具
全称 python-check-updates
简称 pcu
。
主要原因是 Go 非常适合写工具类,因为不需要安装环境即可运行,加上更快,体积也小。
项目开源戳 https://github.com/xjh22222228/python-check-updates
这个项目只是用来玩的,直接用 pip 更好。
Find the latest version of your requirements.txt current dependency package.
Deno ships as a single executable with no dependencies. You can install it using the installers below, or download a release binary from the releases page.
Shell (Mac, Linux):
curl -fsSL https://raw.githubusercontent.com/xjh22222228/python-check-updates/main/install.sh | bash
Show any new dependencies for the project in the current directory:
$ pcu
Checking /opt/requirements_test.txt
13 / 13 [--------------------------] 100.00% 1 p/s
pytest-cov → 2.10.1
pytest-mock ==2.0.0 → 3.3.1
httpbin ==0.7.0 → 0.7.0
pytest-httpbin <1.0 → 1.0.0
MySQL-python ==1.2.5 → 1.2.5
aliyun-python-sdk-cdn ==2.3.1 → 3.5.8
XlsxWriter ==0.9.3 → 1.3.7
aliyun-python-sdk-core ==2.3.2 → 2.13.29
wheel → 0.35.1
service-identity ==16.0.0 → 18.1.0
pytest >=2.8.0,<=3.10.1 → 6.1.2
zope.interface ==4.3.2 → 5.2.0
Done in 1 s.
-f, --file Specify the file name of the check dependency
package, default 'requirements.txt'
-v, --version output the version number
-c, --check Check the latest version
-h, --help display help for command
$ pcu -f=requirements_test.txt
$ pcu -v
基于Flutter。
由于笔者不是专业的APP开发,在这方面较弱,在接入微信登录遇到不少坑,基本都是配置问题,在这里记录下过程。
IOS接入微信登录必须具备以下几点(缺一不可):
1、新建一个文件名叫 apple-app-site-association
没有任何后缀, 并写入以下配置
{
"applinks": {
"apps": [],
"details": [
{
"appID": "1UPF2ET6AP.com.example.app.scp",
"paths": [ "/help/*" ]
}
]
}
}
需要修改 appID
和 paths
。
2、将文件放在域名根目录下。
打开你的域名比如 https://www.example.com/apple-app-site-association
如果文件被下载说明这步没问题。
3、使用 safari 浏览器打开 https://www.example.com/help/123
前面修改为你的域名,help 是前面在 paths 指定的, 123是乱写的随机字符串,打开后如果出现类似下面说明正常:
4、打开微信开放平台,找到IOS配置,下面必须全部都要配置
5、打开APPLE开发者中心,找到 Associated Domains
这个选项将它开启。
XCODE
打开 Runner.xcodeproj
文件。如图配置 Domains, applinks 前缀是固定的,后面就前面配置的 Universal Links
这个干嘛用的呢,主要是添加微信的 scheme 到白名单上去,这一步少不了,如果不添加没有办法知道微信是否已安装(尽管已安装了)。
找到 info.plist
文件, 将下面这一块内容添加到 dict
节点的末位,如下:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>wechat</string>
<string>weixin</string>
<string>weixinULAPI</string>
</array>
如果不知道这个文件在哪里,直接在当前工程下搜索这个文件, 一定有。
接入这微信登录费了不少心思,少一步就要找各种问题进行排除,太蛋疼,还好终于搞定了,祝后面的小老弟们一切顺利哈。
很多情况需要在 宿主 运行容器内的命令, 比如需要在宿主运行容器 nginx / redis / 等命令
有2种方法可以执行容器命令:
1、用内联重定向 EOF
docker exec -it c6261194df8e /bin/bash << EOF
touch /home/inner.txt
EOF
2、docker 参数-c 可以执行容器shell
docker exec -it c6261194df8e /bin/bash -c "touch /home/inner.txt"
用上面2种方法会发现虽然执行了,但是并没有在容器内创建文件,不信可以试试。
目前我还没知道什么问题。
既然无法在宿主内执行容器内的Shell,那是不是可以执行容器Shell脚本?
写 Shell 脚本得有编辑器,容器默认不带 vim
,所以得先安装:
apt-get update && apt-get install vim
Shell 脚本, 这里是Demo,实际参照自己需要执行的Shell。
ci.sh 内容如下:
#!/bin/bash
echo "hello" >> /home/inner.txt
来试试
docker exec -it c6261194df8e /bin/bash -c "/bin/bash /opt/ci.sh"
然后进入容器会发现 /home 目录下确实有 inner.txt 文件,说明这思路是可以的。
对了,执行容器内的外建命令记得用绝对路径执行,例如:
# 必须
/bin/nginx -s reload
# 这样不行的,因为有些外建命令没有加入环境变量
nginx -s reload
在我们编写程序时是离不开日志的,在Go标准库中提供了一个 log
模块。
比较常用的方法有下面这几个:
ln
结尾的只是多了个换行符 \n
, f
结尾的是格式化文本。
很多新手不知道这些方法和 fmt
包中的方法有什么区别。
实际上上面那3个都只是 fmt
包中的语法糖
抛出异常信息并终止程序。
示例代码:
package main
import (
"log"
)
func main() {
log.Panic("error")
}
底层实现是这样子的:
可以看到这其实只是一个语法糖而已
func Panic(v ...interface{}) {
s := fmt.Sprint(v...)
std.Output(2, s)
panic(s)
}
如果说能不能用全局方法 panic
呢? 不行, 因为panic 只接受一个参数:
panic("error")
所以为什么会有 log.Panic
这个方法了吧。
Fatal
和 Panic
都是用来打印信息然后终止程序,不知道何时用哪个?
Panic
: 抛出异常终止程序,一般来说在调试时想获得更多错误信息那就使用 PanicFatal
: 这其实只是打印信息后正常退出程序不会提供更多额外信息给你所以在程序中使用 Fatal
是没什么意义的,所以不推荐使用。
创建日志文件的好处在于可以持久化,在出现问题的时候可以快速定位。
创建日志文件需要借助 os
模块和 log
模块。
示例代码,以注释说明:
package main
import (
"log"
"os"
)
func main() {
// 打开一个文件
// 第一个参数是写入日志文件的位置
// 第二个参数是需要以什么权限进行操作,多个mode用 | 符号分隔代表多个
// 最后参数是权限的八进制表示法
file, err := os.OpenFile("./log.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0)
if err != nil {
log.Panicln("文件打开错误:", err)
}
defer file.Close()
// 用 New 方法实例化
// 第一个参数是 io.Writer 接口,只要实现了该接口都支持,文件就是
// 第二个参数是 前缀信息 一般用于区别日志是属哪个分类
// 最后一个参数是 标志, 也就是系统额外附加信息 LstdFlags 包含了日志和时间
ilog := log.New(file, "Error:", log.LstdFlags)
ilog.Println("输出错误信息")
}
标志有以下(都是以 L 开头):
参数 | 描述 |
---|---|
Ldate | 本地时区日期 2020/11/11 |
Ltime | 本地时区时间 01:23:23 |
Lmicroseconds | 微妙 01:23:23.123123 |
Llongfile | 打印完整文件路径和行号 |
Lshortfile | 打印文件名和行号 |
LUTC | 如果设置了日期或时间,请使用UTC而不是本地时区 |
LstdFlags | Ldate和Ltime的结合,日期和时间一起打印 |
Lmsgprefix | 将Flag信息移至消息前面 |
golang打印日志行号有时非常有用,因为默认 fmt
是不打印行号的,给调试带来不便。
有了上面的Flag信息就好实现了, 借助 Llongfile
即可。
package main
import (
"log"
"os"
)
func main() {
ilog := log.New(os.Stdout, "Info:", log.Llongfile)
ilog.Println("Hello")
// 输出:Info:/Users/main.go:10: Hello
}
目前比较流行的是这两个日志系统,可以去了解下
每次新建项目都会遇到这个提示,明明安装依赖包了, 能用,就是爆红。
解决办法是在 Goland 设置里将 Go Modules 开启即可。
等Vue3很长时间了,一把梭。
Vue3 提供了2种开发模式,Composition API 和 Vue2的导出模式, 以供Vue2.0快速切入。
VueRouter 和 Vuex 没有太大的变化,详细参考文档。