Merge remote-tracking branch 'LCTT/master'

This commit is contained in:
Xingyu Wang 2020-03-17 00:34:27 +08:00
commit eb88d26c9b
7 changed files with 182 additions and 187 deletions

View File

@ -0,0 +1,109 @@
你所不知道的用 less 查看文件的高级用法
======
> 使用 less 文件查看器的一些技巧。
![](https://img.linux.net.cn/data/attachment/album/202003/16/152826assmtybsohopo4b7.png)
最近,我正在拜读 Scott Nesbitt 的文章《[在 Linux 命令行中使用 less 来查看文本文件][1]》,并受到了一些启发,所以我想分享一些使用 `less` 命令的技巧。
### LESS 环境变量
如果你定义了环境变量 `LESS`(例如在 `.bashrc` 中),那么 `less` 会将其视为一个选项列表,就像在命令行中传递给它一样。
我这样定义:
```
LESS='-C -M -I -j 10 -# 4'
```
它的意思是:
* `-C` 通过不从底部滚动来加快全屏打印速度。
* `-M` 在最后一行(状态行)显示更多信息。你可以使用 `-PM` 来自定义显示的信息,但我通常只用 `-M`
* `-I` 忽略搜索中的大小写。
* `-j 10` 在终端的第 10 行而不是第一行显示搜索结果。这样,每次按 `n` 或(`N` 跳到下一个(或上一个)匹配项时,就会有 10 条上下文。
* `-# 4` 当按下向右或向左的箭头时,会向右或向左跳四个字符。默认情况时跳转半个屏幕,我觉得太多了。一般来说,`less` 似乎(至少部分)是按最初开发它时的环境优化的,那时使用慢速调制解调器和低带宽的互联网连接,所以跳过半个屏幕是有意义的。
### PAGER 环境变量
许多程序使用在 `PAGER` 环境变量中的命令来显示信息。因此,你可以在 `.bashrc` 中设置 `PAGER=less`,然后让程序运行 `less`。查看手册页(`man 7 environ`)中是否有其它此类变量。
### -S
`-S` 告诉 `less` 将长行切断而不是将它们换行。除非我在(或我要)查看文件,否则我很少需要这样做。幸运的是,你可以在 `less` 中输入所有命令行选项,就像它们是键盘命令一样。因此,如果我想在文件已经打开的情况下隔断长行,我可以简单地输入 `-S`LCTT 译注:注意大写 `S` ,并按回车)
这是我经常使用的一个例子:
```
su - postgres
export PAGER=less  # 因为我不用在所有的机器上编辑 postgres 的 .bashrc
psql
```
有时当我查看一个 `SELECT` 命令的输出非常宽时,我会输入 `-S` 以便将其格式化的漂亮一些。如果当我按下右箭头想查看更多内容时它跳得太远(因为我没有设置 `-#`),则可以输入 `-#8`,那么每次按下右箭头都会向右移动八个字符。
有时在多次输入 `-S` 之后,我会退出 psql 并设置环境变量后再次运行它:
```
export LESS=-S
```
### F
命令 `F` 可以使 `less``tail -f` 一样工作,等待更多的数据被添加到文件后再显示它们。与 `tail -f` 相比,它的一个优点是,高亮显示搜索匹配仍然有效。因此,你可以输入 `less /var/log/logfile`,搜索某些内容时,它将高亮显示所有出现的内容(除非你使用了 `-g`),然后按下 `F` 键,当更多数据写入到日志时,`less` 将显示它并高亮新的匹配项。
按下 `F` 后,可以按 `Ctrl+C` 来停止其查找新数据(这不会干掉它),这样你可以返回文件查看旧内容,搜索其它内容等,然后再次按 `F` 键来查看更多新数据。
### 搜索
搜索使用系统的正则表达式库,这通常意味着你可以使用扩展正则表达式。特别是,搜索 `one|two|three` 可以找到并高亮所有的 one、two 或 three。
我经常使用的另一种模式是 `.*someting.*`,特别是对于一些很长的日志行(例如,跨越多个终端宽度的行),它会高亮整行。这种模式使查看一行的起始和结束位置变得更加容易。我还会结合其它内容,例如 `.*one thing.*|.*another thing.*`,或者使用 `key: .*|.*marker.*` 来查看 `key` 的内容。例如,一个日志文件中包含一些字典/哈希的转储。它会高亮相关的标记行,这样我就看到上下文了,甚至,如果我知道这个值被引号引起来的话,就可以:
```
key: '[^']*'|.*marker.*
```
`less` 会保留你的搜索项的历史纪录,并将其保存到磁盘中以备将来调用。当你按下 `/``?` 时,可以使用向上或向下箭头浏览历史记录(以及进行基本的行编辑)。
在撰写本文时,我无意间看了下 `less` 手册页,发现了一个非常有用的功能:使用 `&!pattern` 跳过无关的行。例如,当我在 `/var/log/messages` 中寻找内容时,经常会一个个迭代使用以下命令:
```
cat /var/log/messages | egrep -v 'systemd: Started Session' | less
cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session' | less
cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session|User Slice' | less
cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session|User Slice|dbus' | less
cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session|User Slice|dbus|PackageKit Daemon' | less
```
但是现在我知道如何在 `less` 中做同样的事情。例如,我可以输入 `&!systemd: Started Session`,然后想要隐藏 `systemd: Starting Session`,所以我输入 `&!`,并使用向上箭头从历史记录中获得上一次搜索的结果。然后我接着输入 `|systemd: Starting Session` 并按下回车,继续以相同的方式添加更多条目,直到我过滤掉足够多的条目,看到更有趣的内容。
### =
命令 `=` 显示有关文件和位置的更多信息,甚至比 `-M` 更多。如果文件非常大,计算 `=` 花费的时间太长,可以按下 `Ctrl+C`,它将停止尝试计算。
如果你正在查看的内容来自管道而不是文件,则 `=`(和 `-M`)不会显示未知内容,包括文件中的行数和字节数。要查看这些数据,如果你知道管道命令将很快结束,则可以使用 `G` 跳到最后,然后 `less` 将开始显示这些信息。
如果按下 `G` 并且写入管道的命令花费的时间比预期的长,你可以按下 `Ctrl+C`,该命令将被终止。即使你没有按 `G``Ctrl+C` 键也会杀死它。因此,如果你不想终止命令,请不要意外按下 `Ctrl+C`。出于这个原因,如果命令执行了某些操作(不仅是显示信息),通常更安全的做法是将其输出写入文件并在单独的终端中查看文件,而不是使用管道。
### 为什么你需要 less
`less` 是一个非常强大的程序,与该领域中较新的竞争者(例如 `most``moar`)不同,你可能会在几乎所有的系统上找到它,就像 `vi` 一样。因此,即使你使用 GUI 查看器或编辑器,花一些时间浏览 `less` 手册页也是值得的,至少可以了解一下它的用处。这样,当你需要做一些已有的功能可能提供的工作时,就会知道如何要搜索手册页或互联网来找到所需的内容。
有关更多信息,访问 [less 主页][2]。该网站有一个不错的常见问题解答,其中包含更多提示和技巧。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/5/advanced-use-less-text-file-viewer
作者:[Yedidyah Bar David][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/didib
[1]:http://opensource.com/article/18/4/using-less-view-text-files-command-line
[2]:http://www.greenwoodsoftware.com/less/

View File

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: translator: (messon007)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: (chai-yuan)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: (zhangxiangping)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
@ -264,7 +264,7 @@ via: https://opensource.com/article/19/7/python-google-natural-language-api
作者:[JR Oakes][a]
选题:[lujun9972][b]
译者:[zhangxiangping](https://github.com/zhangxiangping)
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,111 +0,0 @@
Linux 中使用 less 查看文件的高级用法
======
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_terminals_0.png?itok=XwIRERsn)
最近,我正在拜读 Scott Nesbitt 的文章“[在 Linux 中使用 less 命令来查看文本文件][1]”,并受到了一些启发,所以我想分享一些使用 `less` 命令的技巧。
### LESS 环境变量
如果你定义了环境变量 `LESS`(例如在 `.bashrc` 中),那么 `less` 会将其视为一个选项列表,就像在命令行中传递给它一样。
我这样定义:
```
LESS='-C -M -I -j 10 -# 4'
```
它的意思是:
* `-C` 通过不从底部滚动来加快全屏打印速度。
* `-M` 在最后一行(状态行)显示更多信息。你可以使用 `-PM` 来自定义显示的信息,但我通常只用 `-M`
* `-I` 忽略搜索中的大小写。
* `-j 10` 在终端的第 10 行而不是第一行显示搜索结果。这样,每次按 `n` 或(`N` 跳到下一个(或上一个)匹配项时,就会有 10 条上下文。
* `-# 4` 当按下向右或向左的箭头时,会向右或向左跳四个字符。默认情况时跳转半个屏幕,我觉得太多了。一般来说,`less` 似乎(至少部分)优化了最初开发时的环境,使用慢速调制解调器和低带宽的互联网连接,这样可以跳过半个屏幕。
### PAGER 环境变量
许多程序使用在 `PAGER` 环境变量中的命令来显示信息。因此,你可以在 `.bashrc` 中设置 `PAGER=less`,然后让程序运行 `less`。查看 man 页(`man 7 environ`)中是否有其它此类变量。·
### -S
`-S` 告诉 `less` 将长行隔断而不是将它们包起来。除非或直到我开始查看文件,否则我很少需要这样做。幸运的是,你可以在 `less` 中输入所有命令行选项,就像它们是键盘命令一样。因此,如果我想在文件已经打开的情况下隔断长行,我可以简单地输入 `-S`
这是我经常使用的一个例子:
```
    su - postgres
    export PAGER=less  # 因为我没在所有的机器上编辑 postgres .bashrc而是在 psql 使用
```
有时当我查看一个 `SELECT` 命令的输出非常宽,我会输入 `-S` 以便将其格式化。如果当我按下右箭头想查看更多内容时它跳得太远(因为我没有设置 `-#`),则可以输入 `-#8`,那么每次按下右箭头都会向右移动八个字符。
有时在多次输入 `-S` 之后,我会退出 psql 并设置环境变量后再次运行它:
```
export LESS=-S
```
### F
命令 `F` 使 `less``tail -f` 一样工作,等待更多的数据被添加到文件后再显示。与 `tail -f` 相比,它的一个优点是,高亮显示搜索匹配仍然有效。因此,你可以输入 `less /var/log/logfile`,搜索某些内容时,它将高亮显示所有出现的内容(除非你使用了 -g然后按下 `F` 键,当更多数据写入到日志时,`less` 将显示它并高亮新的匹配项。
按下 `F` 后,可以按 `Ctrl+C` 来停止其查找新数据(这不会干掉它),这样你可以返回文件查看旧内容,搜索其它内容等,然后再次按 `F` 键来查看更多新数据。
### 搜索
搜索使用系统的 regexp 库,这通常意味着你可以使用扩展正则表达式。特别是,搜索 `one|two|three` 将找到并高亮所有的 one、two 或 three。
我经常使用的另一种模式是 `.*someting.*`,特别是对于一些很长的日志行(例如,跨越多个终端行),它会高亮整行。这种模式使查看一行的起始和结束位置变得更加容易。我还会结合其它内容,例如 `.*one thing.*|.*another thing.*`,或者使用 `key: .*|.*marker.*` 来查看 `key` 的内容。例如,一个日志文件中包含一些字典/哈希的转储。它会高亮相关的标记行,这样我就有上下文了,甚至,如果我知道这个值被引号引起来的话,就可以:
```
key: '[^']*'|.*marker.*
```
`less` 会保留你搜索项的历史纪录,并将其保存到磁盘中以备将来调用。当你按下 `/``?` 时,可以使用向上或向下箭头浏览历史记录(以及基本的行编辑)。
在撰写本文时,我无意间看了下 less 手册页,发现了一个非常有用的功能:使用 `&!pattern` 跳过无趣的行。例如,当我在 `/var/log/messages` 中寻找内容时,经常会遍历以下命令:
```
    cat /var/log/messages | egrep -v 'systemd: Started Session' | less
    cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session' | less
    cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session|User Slice' | less
    cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session|User Slice|dbus' | less
    cat /var/log/messages | egrep -v 'systemd: Started Session|systemd: Starting Session|User Slice|dbus|PackageKit Daemon' | less
```
但是现在我知道如何在 `less` 中做同样的事情。例如,我可以输入 `&!systemd: Started Session`,然后决定删除 `systemd: Starting Session`,所以我输入 `&!`,并使用向上箭头从历史记录中获得上一次搜索的结果。然后我输入 `|systemd: Starting Session` 并按下 `Enter`,继续以相同的方式添加更多条目,直到我过滤掉足够多的条目,看到更有趣的内容。
### =
命令 `=` 显示有关文件和位置的更多信息,甚至比 `-M` 更多。如果文件非常大,计算 `=` 花费的时间太长,可以按下 `Ctrl+C`,它将停止尝试。
如果你正在查看的内容来自管道而不是文件,则 `=` (和 `-M`)不会显示未知内容,包括文件中的行数和字节数。要查看这些数据,如果你知道管道命令将很快结束,则可以使用 `G` 跳到最后,然后 `less` 将开始显示这些信息。
如果按下 `G` 并且写入管道的命令花费的时间比预期的长,你可以按下 `Ctrl+C`,该命令将被终止。即使你没有按 `G``Ctrl+C` 键也会杀死它。因此,如果你不想杀死它,请不要意外按下 `Ctrl+C`。出于这个原因,如果命令执行了某些操作(不仅是显示信息),通常更安全的做法是将其输出写入文件并在单独的终端中查看文件,而不是使用管道。
### 为什么你需要 less
`less` 是一个非常强大的程序,与该领域中较新的竞争者(例如 most 和 moar不同你可能会在几乎所有的系统上找到它就像 `vi` 一样。因此,即使你使用 GUI 查看器或编辑器,花一些时间浏览 `less` 手册页也是值得的,至少可以了解以下可用的内容。这样,当你需要做一些现有功能可能涉及的工作时,就会知道如何要搜索手册页或互联网来找到所需的内容。
有关更多信息,访问 [less 主页][2]。网站有一个不错的常见问题解答,其中包含更多提示和技巧。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/5/advanced-use-less-text-file-viewer
作者:[Yedidyah Bar David][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[译者ID](https://github.com/MjSeven)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/didib
[1]:http://opensource.com/article/18/4/using-less-view-text-files-command-line
[2]:http://www.greenwoodsoftware.com/less/

View File

@ -7,35 +7,33 @@
[#]: via: (https://nicolasparada.netlify.com/posts/go-messenger-conversations/)
[#]: author: (Nicolás Parada https://nicolasparada.netlify.com/)
Building a Messenger App: Conversations
构建一个即时消息应用(三):对话
======
This post is the 3rd in a series:
本文是该系列的第三篇。
* [Part 1: Schema][1]
* [Part 2: OAuth][2]
* [第一篇:模式][1]
* [第二篇:OAuth][2]
在我们的即时消息应用中,消息表现为两个参与者对话的堆叠。如果你想要开始异常对话,就应该向应用提供你想要交谈的用户,而当对话创建后(如果该对话此前并不存在),就可以向该对话发送消息。
就前端而言,我们可能想要显示一份近期对话列表。并在此处显示对话的最后一条消息以及另一个参与者的姓名和头像。
In our messenger app, messages are stacked by conversations between two participants. You start a conversation providing the user you want to chat with, the conversations is created (if not exists already) and you can start sending messages to that conversations.
在这篇帖子中我们将会编写一些端点endpoints来完成像「创建对话」、「获取对话列表」以及「找到单个对话」这样的任务。
On the front-end were interested in showing a list of the lastest conversations. There well show the last message of it and the name and avatar of the other participant.
首先,要在主函数 `main()` 中添加下面的路由。
In this post, well code the endpoints to start a conversation, list the latest and find a single one.
Inside the `main()` function add this routes.
```
```go
router.HandleFunc("POST", "/api/conversations", requireJSON(guard(createConversation)))
router.HandleFunc("GET", "/api/conversations", guard(getConversations))
router.HandleFunc("GET", "/api/conversations/:conversationID", guard(getConversation))
```
These three endpoints require authentication so we use the `guard()` middleware. There is a new middleware that checks for the request content type JSON.
这三个端点都需要进行身份验证,所以我们将会使用 `guard()` 中间件。我们也会构建一个新的中间件,用于检查请求内容是否为 JSON 格式。
### Require JSON Middleware
### JSON 请求检查中间件
```
```go
func requireJSON(handler http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if ct := r.Header.Get("Content-Type"); !strings.HasPrefix(ct, "application/json") {
@ -47,11 +45,11 @@ func requireJSON(handler http.HandlerFunc) http.HandlerFunc {
}
```
If the request isnt JSON, it responds with a `415 Unsupported Media Type` error.
如果请求request不是 JSON 格式,那么它会返回 `415 Unsupported Media Type`(不支持的媒体类型)错误。
### Create Conversation
### 创建对话
```
```go
type Conversation struct {
ID string `json:"id"`
OtherParticipant *User `json:"otherParticipant"`
@ -60,9 +58,9 @@ type Conversation struct {
}
```
So, a conversation holds a reference to the other participant and the last message. Also has a bool field to tell if it has unread messages.
就像上面的代码那样,对话中保持对另一个参与者和最后一条消息的引用,还有一个 bool 类型的字段,用来告知是否有未读消息。
```
```go
type Message struct {
ID string `json:"id"`
Content string `json:"content"`
@ -74,11 +72,11 @@ type Message struct {
}
```
Messages are for the next post, but I define the struct now since we are using it. Most of the fields are the same as the database table. We have `Mine` to tell if the message is owned by the current authenticated user and `ReceiverID` will be used to filter messanges once we add realtime capabilities.
我们会在下一篇文章介绍与消息相关的内容,但由于我们这里也需要用到它,所以先定义了 `Message` 结构体。其中大多数字段与数据库表一致。我们需要使用 `Mine` 来断定消息是否属于当前已验证用户所有。一旦加入实时功能,`ReceiverID` 可以帮助我们过滤消息。
Lets write the HTTP handler then. Its quite long but dont be scared.
接下来让我们编写 HTTP 处理程序。尽管它有些长,但也没什么好怕的。
```
```go
func createConversation(w http.ResponseWriter, r *http.Request) {
var input struct {
Username string `json:"username"`
@ -170,19 +168,19 @@ func createConversation(w http.ResponseWriter, r *http.Request) {
}
```
For this endpoint you do a POST request to `/api/conversations` with a JSON body containing the username of the user you want to chat with.
在此端点,你会向 `/api/conversations` 发送 POST 请求,请求的 JSON 主体中包含要对话的用户的用户名。
So first it decodes the request body into an struct with the username. Then it validates that the username is not empty.
因此,首先需要将请求主体解析成包含用户名的结构。然后,校验用户名不能为空。
```
```go
type Errors struct {
Errors map[string]string `json:"errors"`
}
```
This is the `Errors` struct. Its just a map. If you enter an empty username you get this JSON with a `422 Unprocessable Entity` error.
这是错误消息的结构体 `Errors`,它仅仅是一个映射。如果输入空用户名,你就会得到一段带有 `422 Unprocessable Entity`(无法处理的实体)错误消息的 JSON 。
```
```json
{
"errors": {
"username": "Username required"
@ -190,17 +188,17 @@ This is the `Errors` struct. Its just a map. If you enter an empty username y
}
```
Then, we begin an SQL transaction. We only received an username, but we need the actual user ID. So the first part of the transaction is to query for the id and avatar of that user (the other participant). If the user is not found, we respond with a `404 Not Found` error. Also, if the user happens to be the same as the current authenticated user, we respond with `403 Forbidden`. There should be two different users, not the same.
然后,我们开始执行 SQL 事务。收到的仅仅是用户名,但事实上,我们需要知道实际的用户 ID 。因此,事务的第一项内容是查询另一个参与者的 ID 和头像。如果找不到该用户,我们将会返回 `404 Not Found`(未找到) 错误。另外,如果找到的用户恰好和「当前已验证用户」相同,我们应该返回 `403 Forbidden`(拒绝处理)错误。这是由于对话只应当在两个不同的用户之间发起,而不能是同一个。
Then, we try to find a conversation those two users have in common. We use `INTERSECT` for that. If there is one, we redirect to that conversation `/api/conversations/{conversationID}` and return there.
然后,我们试图找到这两个用户所共有的对话,所以需要使用 `INTERSECT` 语句。如果存在,只需要通过 `/api/conversations/{conversationID}` 重定向到该对话并将其返回。
If no common conversation was found, we continue by creating a new one and adding the two participants. Finally, we `COMMIT` the transaction and respond with the newly created conversation.
如果未找到共有的对话,我们需要创建一个新的对话并添加指定的两个参与者。最后,我们 `COMMIT` 该事务并使用新创建的对话进行响应。
### Get Conversations
### 获取对话列表
This endpoint `/api/conversations` is to get all the conversations of the current authenticated user.
端点 `/api/conversations` 将获取当前已验证用户的所有对话。
```
```go
func getConversations(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
authUserID := ctx.Value(keyAuthUserID).(string)
@ -267,17 +265,17 @@ func getConversations(w http.ResponseWriter, r *http.Request) {
}
```
This handler just does a query to the database. It queries to the conversations table with some joins… First, to the messages table to get the last message. Then to the participants, but it adds a condition to a participant whose ID is not the one of the current authenticated user; this is the other participant. Then it joins to the users table to get his username and avatar. And finally joins with the participants again but with the contrary condition, so this participant is the current authenticated user. We compare `messages_read_at` with the message `created_at` to know whether the conversation has unread messages. And we use the message `user_id` to check if its “mine” or not.
该处理程序仅对数据库进行查询。它通过一些联接来查询对话表……首先从消息表中获取最后一条消息。然后依据「ID 与当前已验证用户不同」的条件,从参与者表找到对话的另一个参与者。然后联接到用户表以获取该用户的用户名和头像。最后,再次联接参与者表,并以相反的条件从该表中找出参与对话的另一个用户,其实就是当前已验证用户。我们会对比消息中的 `messages_read_at``created_at` 两个字段,以确定对话中是否存在未读消息。然后,我们通过 `user_id` 字段来判定该消息是否属于「我」(指当前已验证用户)。
Note that this query assumes that a conversation has just two users. It only works for that scenario. Also, if you want to show a count of the unread messages, this design isnt good. I think you could add a `unread_messages_count` `INT` field on the `participants` table and increment it each time a new message is created and reset it when the user read them.
注意,此查询过程假定对话中只有两个用户参与,它也仅仅适用于这种情况。另外,该设计也不很适用于需要显示未读消息数量的情况。如果需要显示未读消息的数量,我认为可以在 `participants` 表上添加一个`unread_messages_count` `INT` 字段,并在每次创建新消息的时候递增它,如果用户已读则重置该字段。
Then it iterates over the rows, scan each one to make an slice of conversations and respond with those at the end.
接下来需要遍历每一条记录通过扫描每一个存在的对话来建立一个对话切片an slice of conversations并在最后进行响应。
### Get Conversation
### 找到单个对话
This endpoint `/api/conversations/{conversationID}` respond with a single conversation by its ID.
端点 `/api/conversations/{conversationID}` 会根据 ID 对单个对话进行响应。
```
```go
func getConversation(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
authUserID := ctx.Value(keyAuthUserID).(string)
@ -321,15 +319,15 @@ func getConversation(w http.ResponseWriter, r *http.Request) {
}
```
The query is quite similar. Were not interested in showing the last message, so we omit those fields, but we need the message to know whether the conversation has unread messages. This time we do a `LEFT JOIN` instead of an `INNER JOIN` because the `last_message_id` is `NULLABLE`; in other case we wont get any rows. We use an `IFNULL` in the `has_unread_messages` comparison for that reason too. Lastly, we filter by ID.
这里的查询与之前有点类似。尽管我们并不关心最后一条消息的显示问题,并因此忽略了与之相关的一些字段,但是我们需要根据这条消息来判断对话中是否存在未读消息。此时,我们使用 `LEFT JOIN` 来代替 `INNER JOIN`,因为 `last_message_id` 字段是 `NULLABLE`(可以为空)的;而其他情况下,我们无法得到任何记录。基于同样的理由,我们在 `has_unread_messages` 的比较中使用了 `IFNULL` 语句。最后,我们按 ID 进行过滤。
If the query returns no rows, we respond with a `404 Not Found` error, otherwise `200 OK` with the found conversation.
如果查询没有返回任何记录,我们的响应会返回 `404 Not Found` 错误,否则响应将会返回 `200 OK` 以及找到的对话。
* * *
Yeah, that concludes with the conversation endpoints.
本篇帖子以创建了一些对话端点结束。
Wait for the next post to create and list messages 👋
在下一篇帖子中,我们将会看到如何创建并列出消息。
[Souce Code][3]
@ -346,6 +344,6 @@ via: https://nicolasparada.netlify.com/posts/go-messenger-conversations/
[a]: https://nicolasparada.netlify.com/
[b]: https://github.com/lujun9972
[1]: https://nicolasparada.netlify.com/posts/go-messenger-schema/
[2]: https://nicolasparada.netlify.com/posts/go-messenger-oauth/
[1]: https://linux.cn/article-11396-1.html
[2]: https://linux.cn/article-11510-1.html
[3]: https://github.com/nicolasparada/go-messenger-demo

View File

@ -1,28 +1,30 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12001-1.html)
[#]: subject: (Basilisk: A Firefox Fork For The Classic Looks and Classic Extensions)
[#]: via: (https://itsfoss.com/basilisk-browser/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
Basilisk一个有着经典外观和经典扩展的 Firefox 分支
Basilisk一个有着经典的外观和扩展的 Firefox 复刻
======
_ **简介Basilisk 是一个 Firefox 分支,它支持旧版扩展等更多功能。在这里,我们看一下它的功能并尝试一下。**_
> Basilisk 是一个 Firefox 复刻,它支持旧版的扩展等更多功能。在这里,我们看一下它的功能并尝试一下。
![](https://img.linux.net.cn/data/attachment/album/202003/16/130319lvls6fvsaslzllrv.jpg)
### Basilisk基于 XUL 的开源 Web 浏览器
尽管最好使用 Linux上的常规浏览器如 Firefox 或 Chromium但了解其他浏览器也没坏处。最近我偶然发现了一个 Firefox 分支,[Basilisk][1] 浏览器,它有经典的 Firefox 用户界面以及旧版扩展支持(就像 [Waterfox][2] 一样)。
尽管最好使用 Linux 上的常规浏览器(如 Firefox 或 Chromium但了解其他浏览器也没坏处。最近我偶然发现了一个 Firefox 复刻:[Basilisk][1] 浏览器,它有经典的 Firefox 用户界面以及旧版扩展支持(就像 [Waterfox][2] 一样)。
![itsfoss.com homepage on Basilisk][3]
如果你迫切需要使用旧版扩展程序或怀念 Firefox 的经典外观Basilisk 浏览器可以帮到你。这个浏览器是由 [Pale Moon][4] 浏览器背后的团队维护(这是我接下来要介绍的另一个 Firefox 分支)。
如果你迫切需要使用旧版扩展程序或怀念 Firefox 的经典外观Basilisk 浏览器可以帮到你。这个浏览器是由 [Pale Moon][4] 浏览器背后的团队维护(这是我接下来要介绍的另一个 Firefox 复刻)。
如果你正在寻找开源 [Chrome 替代品][5],那么你可以快速了解一下 Basilisk 提供的功能。
**注意:**_Basilisk 是开发中软件。即使我在使用时没有遇到重大的可用性问题,但你也不应依赖它作为唯一使用的浏览器。_
**注意:**Basilisk 是开发中软件。即使我在使用时没有遇到重大的可用性问题,但你也不应依赖它作为唯一使用的浏览器。
### Basilisk 浏览器的特性
@ -30,23 +32,21 @@ _ **简介Basilisk 是一个 Firefox 分支,它支持旧版扩展等更多
Basilisk 开箱即用。但是,在考虑使用之前,可能需要先看一下以下这些特性:
* 基于 [XUL][7] 的 Web 浏览器
  * 它具有 “Australis” Firefox 界面,着在 v29v56 的 Firefox 版本中非常流行。
  * 支持 [NPAPI][8] 插件Flash、Unity、Java 等)
  * 支持 XUL/Overlay Mozilla 形式的扩展。
  * 使用 [Goanna][9] 开源浏览器引擎,它是 Mozilla [Gecko][10] 的分支
  * 不使用 Rust 或 Photon 用户界面
  * 仅支持 64 位系统
* 基于 [XUL][7] 的 Web 浏览器
* 它具有 “Australis” Firefox 界面,这在 v29v56 的 Firefox 版本中非常流行。
* 支持 [NPAPI][8] 插件Flash、Unity、Java 等)
* 支持 XUL/Overlay Mozilla 形式的扩展。
* 使用 [Goanna][9] 开源浏览器引擎,它是 Mozilla [Gecko][10] 的复刻
* 不使用 Rust 或 Photon 用户界面
* 仅支持 64 位系统
### 在 Linux 上安装 Basilisk
你可能没有在软件中心中找到它。因此,你必须前往其官方[下载页面][11]获得 tarballtar.xz文件。
下载后,只需将其解压缩并进入文件夹。接下来,你将在其中找到一个 “**Basilisk**” 可执行文件。你只需双击或右键单击并选择“**运行**”即可运行它。
下载后,只需将其解压缩并进入文件夹。接下来,你将在其中找到一个 `Basilisk` 可执行文件。你只需双击或右键单击并选择 “运行” 即可运行它。
你可以查看它的 [GitHub 页面] [12]获取更多信息。
你可以查看它的 [GitHub 页面][12]获取更多信息。
![][13]
@ -58,22 +58,21 @@ cd basilisk
./basilisk
```
[Download Basilisk][1]
- [下载 Basilisk][1]
### 使用 Basilisk 浏览器
![][14]
如果你想要旧版扩展支持Basilisk 是不错的 Firefox 分支。它是由 Pale Moon 背后的团队积极开发的,对于希望获得 Mozilla Firefox在 Quantum 更新之前)经典外观,且不包括现代 Web 支持的用户而言,它可能是一个不错的选择。
如果你想要支持旧版扩展Basilisk 是不错的 Firefox 复刻。它是由 Pale Moon 背后的团队积极开发的,对于希望获得 Mozilla Firefox在 Quantum 更新之前)经典外观,且不包括现代 Web 支持的用户而言,它可能是一个不错的选择。
浏览网页没有任何问题。但是,我注意到 “**YouTube**” 将其检测为过时的浏览器,并警告说它将很快停止支持它。
浏览网页没有任何问题。但是,我注意到 YouTube 将其检测为过时的浏览器,并警告说它将很快停止支持它。
**因此,我不确定 Basilisk 是否适合所有现有的 Web 服务 —— 但是,如果你确实需要使用 Firefox 较早版本中的扩展,那这是一个解决方案。**
_**因此,我不确定 Basilisk 是否适合所有现有的 Web 服务-但是,如果你确实需要使用在 Firefox 较早版本中的扩展,那这是一个解决方案。**_
### 总结
**总结**
你认为 Firefox 分支值得尝试吗?你喜欢哪个?在下面的评论中分享你的想法。
你认为这个 Firefox 复刻值得尝试吗?你喜欢哪个?在下面的评论中分享你的想法。
--------------------------------------------------------------------------------
@ -82,7 +81,7 @@ via: https://itsfoss.com/basilisk-browser/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出