#1058 Golang text/template 的用法

2024-09-09

基础示例

package main

import (
    "fmt"
    "os"
    "strings"
    "text/template"
    "time"
)

const TEMPLTE = `{{ .Subject }}
Time: {{ .Time.Format "2006-01-02 15:04:05" }}
Source: {{ .Source }}

{{ .Body }}`

func main() {
    tmpl01, _ := template.New("tmpl01").Parse("你好,{{ . }}")
    tmpl01.Execute(os.Stdout, "世界")

    fmt.Println()
    fmt.Println(strings.Repeat("=", 80))
    fmt.Println()

    type Message struct {
        Subject string
        Time    time.Time
        Source  string
        Body    string
    }

    // http://www.xinhuanet.com/politics/2020-02/08/c_1125546135.htm
    subject := "国家监察委员会调查组已抵达武汉"
    timeobj, _ := time.Parse("2006-01-02 15:04:05", "2020-02-08 13:49:38")
    source := "新华社“新华视点”微博"
    content := "中央纪委国家监委网站8日消息,国家监察委员会调查组已抵达武汉。经中央批准,国家监察委员会派出调查组赴湖北省武汉市,就群众反映的涉及李文亮医生的有关问题作全面调查。"

    tmpl02, _ := template.New("tmpl02").Parse(TEMPLTE)
    tmpl02.Execute(os.Stdout, Message{subject, timeobj, source, content})
}

语法说明

  1. 双花括号
{{ . }}  // 输出当前变量
{{ .Name }} // 输出当前变量的 Name 字段

{{/* 注释 */}}
{{- /* 注释(去掉前后空格与换行) */ -}}

{{ if ... }} A {{ end }}
{{ if ... }} A {{ else }} B {{ end }}
{{ if ... }} A {{ else if ... }} B {{ else }} C {{ end }}

{{ range ... }} A {{ end }}
{{ range ... }} A {{ else }} B {{ end }}
{{ range . -}} {{ . }} {{ end -}}
{{ range $key, $val := . -}} ... {{ end -}}

#1056 《我不是药神》与仿制药

2024-09-01

《我不是药神》中的印度仿制药,并不是简单意义上的“盗版药”,而是按照原研药有效成分和技术标准生产的仿制药。关键问题在于,同一种药物可能在印度可以合法生产,但由于不同国家的专利制度不同,在中国销售时却可能涉及专利侵权,这也是电影故事冲突的核心。

印度之所以成为全球最大的仿制药生产国之一,核心原因是其长期采取了鼓励仿制药发展、限制药品专利垄断、扶持本国制药工业的产业政策。

1970年至2005年,印度药品领域长期只保护生产工艺,而不保护药品本身的产品专利。印度企业可以通过逆向研发,采用不同工艺生产与原研药有效成分相同的药物,因此迅速积累了仿制药研发和制造能力。2005年,为履行世界贸易组织《与贸易有关的知识产权协定》义务,印度开始实行药品产品专利保护,但仍通过严格的专利审查、限制“常青专利”、专利异议和强制许可等机制,为仿制药保留发展空间。

所谓“印度出让人体试药权,作为获得廉价药利益交换”的说法并不准确,至少不能作为印度仿制药产业崛起的主要原因。印度确实拥有庞大的临床试验市场,也曾出现临床试验监管不足、受试者权益保护问题,但没有证据表明印度与外国药企存在所谓“用人体试验换取廉价仿制药”的国家层面交易。印度廉价药的根本原因仍是专利制度、产业政策、低成本制造和长期技术积累。

那么,救命药是不是应该让所有患者买得起?从公共卫生角度,答案当然应该是尽可能降低患者负担;但现实中还存在一个矛盾:新药研发需要巨额投入,专利制度给予药企一定期限的市场独占权,以回收研发成本并维持研发动力。因此,关键不是简单地“保护专利”或“允许仿制”,而是在创新激励与患者可及性之间寻找平衡。

中国其实也拥有庞大的仿制药产业。根据国家卫健委2018年的公开数据,当时我国近17万个药品批文中,95%以上为仿制药。中国的仿制药主要是在相关专利到期、在中国没有相应专利保护,或者依法获得授权等情况下生产。与之不同,印度在1970年至2005年期间不保护药品产品专利,使本国企业能够更早、更大规模地生产原研药的替代品,这成为印度仿制药产业崛起的重要制度基础。

近年来,中国通过仿制药质量和疗效一致性评价、国家组织药品集中采购、医保谈判等方式降低药品价格,同时建立了药品专利强制许可制度。不过,与印度相比,中国对专利保护和药品创新的整体平衡更加谨慎,强制许可在实践中的使用也非常有限。

因此,中国并不是“不允许仿制药”,而是选择了不同的发展路径。印度更早将仿制药产业作为国家战略,并积极利用国际专利制度中的公共卫生例外;中国则试图在专利保护、药品创新和降低患者负担之间寻找平衡。真正值得讨论的问题,是对于关系公共健康和生命安全的药物,现有制度是否应该提供更有效、更快速的价格干预和专利例外机制。

#1055 Extensible Log Format

2024-08-25

https://en.wikipedia.org/wiki/Extended_Log_Format

相比 Common Log Format (通用日志格式),ELF 是名副其实的可拓展:在头部声明了版本,以及字段。
例如:

#Version: 1.0
#Date: 12-Jan-1996 00:00:00
#Fields: time cs-method cs-uri
00:34:23 GET /foo/bar.html
12:21:16 GET /foo/bar.html
12:45:52 GET /foo/bar.html
12:57:34 GET /foo/bar.html
  • Version: <integer>.<integer>
    The version of the extended log file format used. This draft defines version 1.0.
  • Fields: [<specifier>...]
    Specifies the fields recorded in the log.
  • Software: string
    Identifies the software which generated the log.
  • Start-Date: <date> <time>
    The date and time at which the log was started.
  • End-Date: <date> <time>
    The date and time at which the log was finished.
  • Date: <date> <time>
    The date and time at which the entry was added.
  • Remark: <text>
    Comment information. Data recorded in this field should be ignored by analysis tools.

然后这个字段的声明又有一套规则,可以参考

#1054 知识分享

2024-08-23

隐性知识是危险的

隐性知识又称为"部落知识",指的是有些知识没有文档,只掌握在团队成员的头脑里面。

如果你想掌握这些知识,只有去询问团队成员。

隐形知识的优点是,省去了文档成本,而且询问相关成员比自己阅读文档更快,当然前提是那位成员能够快速响应。

隐形知识的缺点是,一旦团队扩大规模,它就会失败。对于掌握知识的团队成员来说,回答问题所占用的时间是一个拖累,影响了生产力,也拖慢了团队的开发速度。

另一方面,随着团队规模的扩大和知识变得更加分散,你自己阅读文档和观看视频讲座,会比向他人寻求帮助更快速和方便。

所以,团队越是大,就越要避免"隐形知识",所有知识尽量文档化,让团队成员能够方便地查阅。

团队知识分享是一个很重要的事情。

  1. 周会分享
  2. 专题分享/讨论会
  3. 文档维护制度

#1053 Common Log Format (通用日志格式)

2024-08-12
  1. NCSA HTTPd (Apache HTTP Server 前身) 定义的一个标准 Web 服务器日志格式。
  2. 格式:host ident authuser date request status bytes
    例如:127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
  3. 如果哪一个字段没有值,就用 - 代替。
import re
from datetime import datetime

RE_CLF = re.compile(r'(\S+) (\S+) (\S+) \[(.*?)\] "(.*?)" (\d{3}) (\d+|-)')

def parse_clf(log_line):
    match = RE_CLF.match(log_line)
    if not match:
        raise ValueError('Log line does not match CLF format')

    ip_address = match.group(1)
    identity = match.group(2)
    user = match.group(3)
    time_str = match.group(4)
    request_line = match.group(5)
    status_code = int(match.group(6))
    size = match.group(7)

    time_format = '%d/%b/%Y:%H:%M:%S %z'
    timestamp = datetime.strptime(time_str, time_format)

    size = int(size) if size != '-' else None

    return {
        'host': ip_address,
        'ident': identity,
        'authuser': user,
        'date': timestamp,
        'request': request_line,
        'status': status_code,
        'bytes': size,
    }

log_example = '127.0.0.1 user-identifier frank [10/Oct/2000:13:55:36 -0700] 'GET /apache_pb.gif HTTP/1.0' 200 2326'
parsed_log = parse_clf(log_example)
print(parsed_log)
# {'host': '127.0.0.1', 'ident': 'user-identifier', 'authuser': 'frank',
#  'date': datetime.datetime(2000, 10, 10, 13, 55, 36, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200))),
#  'request': 'GET /apache_pb.gif HTTP/1.0', 'status': 200, 'bytes': 2326}

#1052 转载:得到邮件回复的最简单方法

2024-08-11

Netlify 公司希望给用户发邮件,让用户回信提供产品反馈。

但是公司知道,群发邮件的回复率很低。他们就请了一个营销顾问,希望他设法提高邮件回复率。

这个顾问认为,用户不回邮有两个原因:
(1)邮件篇幅太长,大多数人懒得读。
(2)群发邮件都是模板格式,用户觉得这是机器发送的,没必要理睬。

他决定,缩短邮件内容,采用口语表达,看看能不能提高回复率。

他设计了一个 A/B 测试。A 格式是传统样式的邮件,150 多个单词。

结果,邮件回复率是 1%,100 个收信人有 1 个回复。

B 格式是一封更短的邮件,只有 37 个单词。

结果,回复率上升到了 4%。邮件长度减少到了四分之一,但是回复率变成了四倍。

他一不做二不休,索性将邮件删到 14 个单词,就是直接了当的一个问题。

这一次,回复率进一步上升到了 8%。

因此,营销邮件提高效果的最简单方法,就是删除任何的多余词汇,尽可能短。


阮一峰是转载的 To Get More Replies, Say Less,原文中还附了这个图表,表示上面提到的这种负相关关系:

#1051 团队管理相关思考

2024-08-07

我有好多地方都做的不好,做了一些反思。

目标管理

  1. 所有人的工作一定要有长期目标。
    即便是一些事务性强的岗位,比如技术支持(处理客户问题),也需要制定目标。
    甚至可以说,越是杂事多的岗位,越要长期目标。没有目标,人就会陷入大量杂事包围,失去方向,真就变成打杂的了。
    这对于个人成长、考核评估都是糟糕的影响,升职加薪就更难实现。
    从管理者的角度看,目标不明确,就等于对员工没有要求,完全寄希望于所有人的主观能动性,并且他们正好能够和你同频,和团队目标正好对齐。
    注:有很强主观能动性,积极主动地投身于工作,这样的人应该不多吧!要想无需沟通,就能自动对齐,那真是黄金搭档了。
  2. 个人目标需要和他承担的角色,以及团队的整体目标有关联性。
  3. 每周都需要制定工作计划(团队目标,重点事项)。
    1. 设计到的人必须协同达成这个团队目标(优先级高于其他个人目标)。
      每个人自己的工作可以自己按照自己的计划来推进,但是团队目标需要把控好。
    2. 尽可能涉及多一些人。
    3. 周末(或周一早上)总结、评价。
      • 过程评价:是否按时完成,是否有沟通,是否回头看。
      • 结果评价:完成度,完成效果(对团队目标的促进作用),和预期对比。
    4. 只关注几个重点事项就行了,其他的事情完成就行(如果后面出现问题,就需要简单沟通,并酌情考虑在考核中有所体现)。
  4. 目标的制定、目标进度跟踪,都需要保持良好的沟通,及时反馈。
    至少,周三要关注一下大家的进度是否符合预期,有没有遇到难题。
    注:需要有意培养大家主动沟通,及时反馈的习惯。
  5. 好的目标:符合 SMART 原则,明确的事项,有时限,可衡量,可实现(努力能做到),并且和团队目标有关联。

报告

  1. 报告的前提就是要对自己的工作进行有效的总结。
    1. 保持对工作的思考,有助于维持清晰的思路,对个人工作的开展事有益的。
    2. 报告就是和上级沟通,将自己的工作和上级做信息同步
      1. 一项工作做的再好,如果没有能够在团队内做到足够好的信息同步,效果会大打折扣。
      2. 对管理者来讲,主要的精力都投身于一些重要事项,真不会很清楚你的工作究竟如何。
  2. 上级的工作目标是什么,他关心我的哪一个工作进展,换位思考一下。
  3. 成绩是什么,存在的问题是什么,需要的资源是什么?
    1. 成绩部分要有数据支撑(可视化,整洁,要点清晰)、有事例加以辅助说明。
      1. 强调成绩和团队目标的关联,强调团队需要的点。
      2. 个人的付出,做了什么努力,带着提一提。如果时间充足,可以多投入时间(不要啰嗦)。
    2. 问题部分要有解决思路。
      1. 工作计划是否需要调整?
      2. 需要哪些支持?
  4. 要丰富自己的知识框架,基于这些再整理出报告框架,这样思考问题会更加全面一些。
    1. 尽量多追问自己一些问题,报告完成之后总结一下,对于新提出来的问题我为什么没有事先想到。

沟通

  1. 多听多看。
    应该鼓励员工的反馈,少打断他。要有耐心。
  2. 感染力:表情,眼神交流,肢体动作。
  3. 这一次沟通的目的是什么?重复,重复,重复。
    如果是重要事项,需要抓住一切机会,多重复几遍。
  4. 培养感情。

#1050 清代女科学家王贞仪

2024-07-26

王贞仪(1768 年—1797 年),字德卿,女,原籍安徽天长,生于江苏南京,清朝天文学家。王贞仪通过艰苦努力自学天文学,数学,地理和医学等科目,突破了当时的封建习俗对女性权利的阻碍。她是一位非常聪明的女性,因其在天文学,数学和诗歌方面的贡献而闻名。她也是一位广受赞誉的学者,是“18 世纪中国的一位非凡女性”。

#1049 DBeaver on MacBook

2024-06-24

今天,办公电脑出了故障(电源坏了),我切换到 MacBook 工作。
用了很多年的 HeidiSQL 没有 Mac 版本,只能用跨平台的 DBeaver 社区版了。

brew install --cask dbeaver-community
  1. 安装目录:

    Windows: C:\Users\nosch\AppData\Local\DBeaver
    MacOS: /Applications/DBeaver.app/

  2. 配置文件目录:

    Windows: C:\Users\nosch\AppData\Roaming\DBeaverData
    Ubuntu: ~/snap/dbeaver-ce/current/.local/share/DBeaverData
    MacOS: ~/Library/Application Support/DBeaverData

    $ tree -a
    .
    ├── .workspaces
    ├── drivers // 驱动相关,忽略
    ├── secure
    │   └── secure_storage
    ├── settings
    │   └── global-settings.ini
    └── workspace6
        ├── .metadata // 忽略
        └── General
            ├── .dbeaver
            │   ├── credentials-config.json
            │   ├── data-sources.json
            │   └── project-settings.json
            ├── .project
            └── .settings
                └── org.eclipse.core.resources.prefs
    

    PS: 默认给我创建的工作区叫做:workspace6
    PS:用户配置在 workspace6/General/.dbeaver/ 目录,连接信息在 data-sources.json 中,但是密码是加密的,保存在 credentials-config.json 中。

  3. 创建第一个 MySQL 数据库连接时,需要下载 MySQL 驱动。
    DBeaver 支持几十种不同的库,包括 NoSQL,例如 MongoDB 和 Redis,不过 NoSQL 功能需要付费,每个月几十刀。

从 HeidiSQL 导出配置文件到 DBeaver

我之前有一个脚本导出 HeidiSQL 数据库配置到 JSON 文件中。
这次直接写一个脚本来从 JSON 同步到 DBeaver 配置文件。

配置文件同步

ln -sf ~/Documents/Mine/Sync/DBeaver ~/Library/DBeaverData/workspace6/General