Minimal and Clean blog theme for Hugo

systemd


参考1

使用spring boot创建的项目,使用maven打包出来成jar包。上传到服务器,这里使用linux的systemd来开启和关闭java程序。

首先找到用户定义的service目录,ubuntu是在/etc/systemd/system,其他发行版可能在/usr/lib/systemd/system/

第二步,在其中创建文件名字.service,我的是叫blog.service,编辑文件。

可以设置工作目录

[unit]
Description=webserver Daemon

[Service]
WorkingDirectory=/root
ExecStart=/root/77kpi
User=root

[Install]
WantedBy=multi-user.target

可以不设置工作目录

[Unit]
Description=webserver Daemon

[Service]
ExecStart=/usr/bin/java -jar /web/server.jar
User=ubuntu

[Install]
WantedBy=multi-user.target

启动Java程序,设置最大内存。

ExecStart=/usr/bin/java -XX:+UseSerialGC -Xss512k -XX:MaxRAM=128m -jar /home/ubuntu/image-0.0.4-SNAPSHOT.jar

第三步,启动/关闭/查看状态。

命令可以这样用:

sudo systemctl start blog.service # starts the service
sudo systemctl stop blog.service # stops the service

sudo systemctl status blog.service
sudo systemctl restart blog.service # restarts the service

sudo systemctl enable blog.service # auto starts the service
sudo systemctl disable blog.service # stops autostart

还可以这样用:

Read more ⟶

Linux安装openvpn客户端


install openvpn client on Linux server
Read more ⟶

利用标准库进行排序


将切片内元素按字母顺序排序。

import (
  sort
)
func demo() {
  var a = []string{"edf","fgh","abc","bad"}
  // 就是一个字符串切片,可以正常用切片的方法操作,如append之类的
	var keys sort.StringSlice
	for k, _ := range a {
		keys = append(keys, k)
	}
	keys.Sort()
	fmt.Println(keys)
	// 清空
	keys = sort.StringSlice{}
}

自定义数据结构的排序

ByOrdinal结构体实现了排序接口,然后用标准库的sort进行排序。

type ByOrdinal []Column

func (o ByOrdinal) Len() int           { return len(o) }
func (o ByOrdinal) Swap(i, j int)      { o[i], o[j] = o[j], o[i] }
func (o ByOrdinal) Less(i, j int) bool { return o[i].Ordinal < o[j].Ordinal }

// 
import (
	"sort"
)

var columns []Column
columns = make([]Column, 0)
sort.Sort(ByOrdinal(columns))
Read more ⟶

IOS的固定列头滚动效果


用jQuery实现一个类似于ios的滚动列表效果,列表头会固定。

https://codepen.io/seansean11/pen/MYbMpw

<head>
    <title>iOSList | iPhone-Style Alphabetical Contact List with HTML, CSS and JavaScript (jQuery) by Brian Hadaway</title>
</head>
<body>
    <div id="list1">
        <div class="ioslist-group-container">
            <div class="ioslist-group-header">A</div>
            <ul>
                <li>Afghanistan</li>
                <li>Akrotiri</li>
                <li>Albania</li>
                <li>Algeria</li>
                <li>American Samoa</li>
            </ul>
        </div>
        <div class="ioslist-group-container">
            <div class="ioslist-group-header">B</div>
            <ul>
                <li>Bahamas, The</li>
                <li>Bahrain</li>
                <li>Bangladesh</li>
                <li>Barbados</li>
                <li>Bassas da India</li>
            </ul>
        </div>
        <div class="ioslist-group-container">
            <div class="ioslist-group-header">C</div>
            <ul>
                <li>Cambodia</li>
                <li>Cameroon</li>
                <li>Canada</li>
                <li>Cape Verde</li>
                <li>Cayman Islands</li>
            </ul>
        </div>
        <div class="ioslist-group-container">
            <div class="ioslist-group-header">D</div>
            <ul>
                <li>Denmark</li>
                <li>Dhekelia</li>
                <li>Djibouti</li>
                <li>Dominica</li>
                <li>Dominican Republic</li>
            </ul>
        </div>
        <div class="ioslist-group-container">
            <div class="ioslist-group-header">E</div>
            <ul>
                <li>Ecuador</li>
                <li>Egypt</li>
                <li>El Salvador</li>
                <li>Equatorial Guinea</li>
                <li>Eritrea</li>
            </ul>
        </div>
        <div class="ioslist-group-container">
            <div class="ioslist-group-header">F</div>
            <ul>
                <li>Falkland Islands (Islas Malvinas)</li>
                <li>Faroe Islands</li>
                <li>Fiji</li>
                <li>Finland</li>
                <li>France</li>
            </ul>
        </div>
        <div class="ioslist-group-container">
            <div class="ioslist-group-header">G</div>
            <ul>
                <li>Gabon</li>
                <li>Gambia, The</li>
                <li>Gaza Strip</li>
                <li>Georgia</li>
                <li>Germany</li>
            </ul>
        </div>
        <div class="ioslist-group-container">
            <div class="ioslist-group-header">H</div>
            <ul>
                <li>Haiti</li>
                <li>Heard Island and McDonald Islands</li>
                <li>Holy See (Vatican City)</li>
                <li>Honduras</li>
                <li>Hong Kong</li>
            </ul>
        </div>
        <div class="ioslist-group-container">
            <div class="ioslist-group-header">I</div>
            <ul>
                <li>Iceland</li>
                <li>India</li>
                <li>Indonesia</li>
                <li>Iran</li>
                <li>Iraq</li>
            </ul>
        </div>
        <div class="ioslist-group-container">
            <div class="ioslist-group-header">J</div>
            <ul>
                <li>Jamaica</li>
                <li>Jan Mayen</li>
                <li>Japan</li>
                <li>Jersey</li>
                <li>Jordan</li>
            </ul>
        </div>
    </div>
</body>

css部分

Read more ⟶

Table固定列头和行头


Read more ⟶

Go的错误处理记录


json.Unmarshal

invalid character ‘\x1f’ looking for beginning of value

网络请求返回的结果是被gzip压缩过的,直接用ioutil.ReadAll读取res.Body的话拿到的是乱码,用 json.Unmarshal 解析的话会报错:

invalid character '\x1f' looking for beginning of value

gzip.NewReader解码一次,可以解决此问题。

func d() {
	client := &http.Client{}
	req, err := http.NewRequest(t.Method, t.Url, strings.NewReader(t.Body))
    res, err := client.Do(req)
    // gzip
	ungzipbody, err := gzip.NewReader(res.Body)
	body, err := ioutil.ReadAll(ungzipbody)
	err = json.Unmarshal(body, c)
}

不知道是不是因为响应头中没有Content-Encoding: gzip

Read more ⟶

Redis基本操作


  1. 进入Redis的命令行
redis-cli
  1. 获取所有的key
keys *
  1. 批量设置 先把命令写到文件中
azu@wangshushuo:~$ cat demo.txt
set k1 v1
set k2 v2
set k3 v3

然后执行命令

cat demo.txt | redis-cli --pipe

哈希Hash

哈希可以理解JS中的对象,命令都是以H开头。

HGET k1 field1
HMGET k1 field1 field2 field3
HGETALL k1

H代表哈希,M代表多个(Multi),k1是哈希的名字,filed是字段名。前两个命令返回来对应字段的value,最后一个命令返回所有的字段和对应的value。

Read more ⟶

了解Golang的writer/reader接口


是什么

首先writer/reader都是接口

type Writer interface {
  Write(p []byte) (n int, err error)
}
type Reader interface {
  Read(p []byte) (n int, err error)
}

他们各有一个动词的方法——读和写,那么就都需要一个宾语,也就是读谁写谁,从接口中是看不到宾语的,而接口在使用时肯定是要通过结构体实现的,所以这个宾语就在结构体中。

比如写信,信就是宾语,信.Write(字),就把字写到了信中。用代码实现如下:

type LetterWriter struct {
  Letter []byte
}
func (l *LetterWriter) Write(p []byte) (n int, err error) {
  l.Letter = append(l.Letter, p...)
  return len(p), nil
}

类似的,读信:

type LetterReader struct {
  Letter []byte
}
func (l *LetterReader) Read(p []byte) (n int, err error) {
  n = copy(p, l.Letter)
  l.Letter = l.Letter[n:]
  return n, nil
}

对于writer和reader,都在结构体中准备了一个字段

使用:

func main() {
  var w LetterWriter
  w.Write([]byte("hello"))
  fmt.Println(w.Letter)
  
  var r LetterReader
  r.Letter = new([]byte, 4)
  
}
type Writer struct {
   buf []byte
}
func (w *Writer) Write(p []byte) (n int, err error) {
   w.buf = append(w.buf, p...)
   return len(p), nil
}
func d() {
  reader := newXReader(source)
  target := make([]byte, length)
  n, err := reader.Read(target)
  fmt.Println(target)
}

将source的值写入target中,Read方法调用一次,读取n(n<=length)个字节的数据到target切片中

Read more ⟶

收集多次请求合并为一次请求


每次请求从原来调用接口改为调collector方法,该方法返回promise,将promise的resolve注册到事件中。在时间窗口内的所有请求的参数会被收集。

在截流函数中发起真正的请求,请求结束后消费掉事件,也会触发promise的resolve。

import { throttle } from 'lodash';

export default class PatchMatch {
  private constructor() {
    this.bus = new EventBus();
  }

  public collector = (id, param) => {
    this.params.push(param);
    this.runner();
    return new Promise((resolve, reject) => {
      this.bus.on(id, resolve);
    });
  };

  private bus: EventBus;

  private params: any[] = [];

  private runner = throttle(() => {
    this.doPatchMatch();
    this.params = [];
  }, 100);

  private doPatchMatch = () => {
    fetch(`${urls.bizFormExtra.patchMatch}`, this.params).then(result => {
      const budgetAccountItems: Array<any> = result.data.data.itemBudgetAccounts;
      budgetAccountItems.forEach(bItem => {
        this.bus.emit(bItem.itemId, bItem);
      });
    });
  };
}

class EventBus {
  public on = (eventName, callback) => {
    this.eventMap[eventName] = callback;
  };
  private eventMap: { [key: string]: Function } = {};
  public emit = (eventName, ...args) => {
    const callback = this.eventMap[eventName];
    if (callback) {
      callback(...args);
      this.eventMap[eventName] = undefined
    }
  };
}
Read more ⟶

CSS阴影


水滴

https://codepen.io/mewoma/pen/gOWXQyO

code

code

<div class="drops">
  <div class="drop"></div>
  <div class="drop"></div>
  <div class="drop"></div>
  <div class="drop"></div>
</div>
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body{
  display: flex;
  min-height: 100vh;
  background: #ddd;
  align-items: center;
  justify-content: center;
}
.drops{
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.drop{
  position: absolute;
  width: 200px;
  height: 200px;
  background: transparent;
  border-radius: 63% 37% 43% 57% / 55% 48% 52% 45%;
  box-shadow: inset 10px 10px 10px rgba(0,0,0,0.05),
    15px 25px 10px rgba(0,0,0,0.1),
    15px 20px 20px rgba(0,0,0,0.05),
    inset -10px -10px 15px rgba(255,255,255,0.9);
}
.drop::before{
  content:'';
  position: absolute;
  top: 35px;
  left: 55px;
  background: #fff;
  width: 20px;
  height: 20px;
  border-radius: 63% 37% 58% 42% / 60% 57% 43% 40%;
}
.drop::after{
  content:'';
  position: absolute;
  top: 35px;
  left: 85px;
  background: #fff;
  width: 10px;
  height: 10px;
  border-radius: 63% 37% 43% 57% / 52% 63% 37% 48%;
}

.drop:nth-child(2){
  transform: scale(0.5) translate(-300px,180px);
  border-radius: 58% 42% 36% 64% / 58% 63% 37% 42%;
}

.drop:nth-child(3){
  transform: scale(0.5) translate(300px,150px);
  border-radius: 58% 42% 51% 49% / 44% 53% 47% 56%;
}

.drop:nth-child(4){
  transform: scale(0.35) translate(120px,-450px);
  border-radius: 64% 36% 33% 67% / 49% 53% 47% 51% ;
}

按钮

https://codepen.io/thebabydino/pen/bGrLprB

Read more ⟶