V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  volvo007  ›  全部回复第 22 页 / 共 50 页
回复总数  992
1 ... 18  19  20  21  22  23  24  25  26  27 ... 50  
上面第二个贴错了,应该是这个
https://item.taobao.com/item.htm?spm=a1z10.5-c-s.w4002-22404213529.12.1f3a5c3f89V9Hp&id=653435559515
我认为买现成的对新手更友好。虽然一开始贵了一点,但是人家能用便宜东西出活因为人家是科班的,人家在上面砸了不知道多少时间

另外,有时候你光把板子做好焊好了还不够。硬件也会出 bug ,那么你要调试硬件 bug ,还需要 示波器、万用表、直流电源、逻辑信号发生器 等工具。如果想避免后期反复在硬件上调试,还应该学习一点仿真。专业的有 matlab 的 simulink 模块;一般也可以用 LTSpice 开源的试试,应该够用
一个一个来

esp32 芯片或 package:可以买邮票孔版本,留了引脚但是不带排针,更便宜一点。当然还可以买裸芯片,但你需要自己搞定焊接、usb/串口、wifi 天线。这里是个例子: https://item.taobao.com/item.htm?spm=a230r.1.14.104.6fa964acsoevIf&id=675349632310&ns=1&abbucket=16#detail 我随便找了一个,照着这个样子买就可以了。如果还嫌大,看看这个 https://item.taobao.com/item.htm?spm=a1z10.5-c-s.w4002-22404213529.18.58355c3fAhL4LH&id=675008860742

板子:化学腐蚀你在逗我…… 老老实实 嘉立创 打板去…… 你放 120 个心,比你自己做便宜质量还有保证

PCB 设计:开源的有 KiCad ,简单的可以用 嘉立创 自己的,有在线版本和离线安装版,看你自己选择。为此你还要学习元件、元件库、原理图、原理图库、原理图设计,以及后续的绘制、布线、简单渲染等步骤。电路板没有 3 层的,只有 1 、2 、4 、6 ... 等层数…… 开孔是直接板子设计时开好,别人会帮你加工的,不要胡思乱想……

元件选型:元件量少可以去某宝买应付一下。长期做就要去大一点的专门的在线平台采购,比如 https://activity.szlcsc.com/newuser.html?c=BD 这里。此外,还应该学习并熟悉自己感兴趣领域的常用芯片和其主要电气特征。IC 就像编程的库一样,选得好可以快速出活事半功倍。有些元件是可以替换的,贵的和便宜的都能用,那为啥卖的贵?自己要多思考

外壳设计:学一下 Fusion360 ,个人用户可以免费用 3 年。教程很多对新手也很友好。如果只是渲染,blender 也可以学一下,渲染效果好很多,又简单好学。(没想到 JLC 现在外壳都能做了……)

pcb 焊接:打板回来之后,当然需要焊接零件(土豪可选择 嘉立创 smt 激光贴片给你做好)。那么你电烙铁、焊锡丝、焊浆、焊油、吸锡器(带)总要准备吧。如果零件数量多,可能还需要带风枪的焊台或者预加热板

外壳加工:看你用什么材质。3d 打印、树脂(可做透明)、亚克力雕刻。价格各不相同,十几块到一百多都有。如果想自己玩,就要添置对应设备,3d 打印机 ( 2k - 6k ),树脂微毒初学不要玩,雕刻机( 3k - 15k )

都是坑,扎扎实实思考并实践吧
2022-11-15 11:37:07 +08:00
回复了 ddvswgg 创建的主题 Apple 求推荐 Macbook 双肩包
觉得通勤不怕的也可以试试 『神秘农场 2day 』😄
2022-11-15 10:44:29 +08:00
回复了 berchtesgaden 创建的主题 iPad iPad 上有什么好用的 markdown 文档项目阅读 app?
Obsidian 能用吗
2022-11-07 23:57:34 +08:00
回复了 volvo007 创建的主题 Go 编程语言 小白学完 channel 马上就不会了 —— 现在会了(大概)
补充一下,WaitGroup 是一个计数信号量,可以用来记录并维护运行的 goroutine ,不是线程池。高手们看看笑笑就好,新手们记得自己脑子里做下替换哈

此外文章里还有些概念、描述上的问题(毕竟不是专业的)。我将测试过的完整代码发到这里大家可以自取

https://pastebin.com/aHCGYfEr

已知问题:由于一开始会有若干线程同时尝试创建文件夹,所以会有几个 "file existed" 错误。捕获打印之后可以继续执行代码
2022-11-07 14:16:34 +08:00
回复了 volvo007 创建的主题 Go 编程语言 小白学完 channel 马上就不会了 —— 现在会了(大概)
@zjj19950716 嗯嗯,好的,是叫 『等待组』吗?
2022-11-07 12:15:59 +08:00
回复了 volvo007 创建的主题 Go 编程语言 都说 go 简单 小白学完 channel 马上就不会了
这篇主题发表于 180 天前。我也去爆栈问过,但是回答都和我这样操作文件不安全相关,并没有正面解决这个问题。

期间我去和单片机嗑了一段时间,当然还有各种本职工作,关于 goroutine 、channel 、sync 库 之类的东西没有顾得上。前几周工作稍微松了一点,这个话题又在心里浮现出来,总觉得是个坎,不彻底搞清楚的话自己这关过不去,也别谈掌握 golang 了。另外,我还注意到这个话题不断有零星的用户在关注,又让我感觉自己好像是个逃兵,问题还没解决我就跑了……

言之种种,在我做了一些针对 channel 的练习之后,算是大概搞清楚了这个例子要怎么写。可能不是 best practice ,但希望能帮到大家,特别是一直关注这个帖子的朋友。

========
在开始之前,我们稍微回顾一下之前的逻辑。相关函数见主题帖子的最后一部分

抽象一下这个主题的使用场景:
函数 1 是一个简单、耗时很短的功能;函数 2 则是一个复杂、耗时长的功能。
我们期待通过 goroutine 来并发处理 函数 2 以达到提升处理性能的目的。

我用的文件处理案例,根据大佬们所说会有线程安全问题,我们先忽略这个问题,主要还是把握后面的方法论哈

1. 函数 getInfo (f []fs.FileInfo, c chan<- string) 通过遍历 []fs.FileInfo 结构,进行了一些简单判断后(例如忽略文件夹、.DS_store 这种),不断将文件名写入 c 这个 string channel 中

2. 函数 dealInfo (path string, typeDict map[string]int, c <-chan string) 通过 range 方法,不断获取 c 之前保存的文件名,截取后缀之后,要么转入对应文件夹,要么创建新文件夹再转入

========
到这里其实思路上是没有什么问题的,这里最关键的是没有注意到简单练习里不会提到的一个知识点:**用 range 遍历 channel 的时候,需要主动 close channel. 否则 range 会阻塞 channel 直到 deadlock panic**. 尽管所有 channel 会在 main channel 结束的时候被强制结束.

如果不用 range 的方式来遍历的话,我们需要写一个 if _, ok := <- c; ok { ... } 这样的东西放倒一个死循环里面,也就是每次循环都要来手动判断一次 c 里面还有没有东西,没东西了我就跳出循环呗。显然 range 遍历的方式更优雅,但要考虑 channel close 的时机。

第二个点则是如何 “并发” 处理 函数 2 。如果只用 go func(),最多只能实现两个 goroutine 之间的通信,所以我们引入了线程池 sync 库来解决这个问题——我们需要给每个 goroutine 加入到线程池里面,但在某个线程工作结束的时候又要把它从池子里面拿掉。最后,还需要一个 wait 函数来通知主线程等待这些线程工作结束。

具体来说,我们需要改写一下前面的函数 1 、函数 2 了:

对于函数 1 ,原始伪代码:
func getInfo(f []fs.FileInfo, c chan<- string){
遍历 f { 处理后的 fineName 写入 c }
}

现在应当改写为:
func getInfo(f []fs.FileInfo, c chan<- string){
// 后面要用 sync.Add 加入池子,所以这里要减去。加入和减去要匹配, 重要!
defer sync.Done()

遍历 f { 处理后的 fineName 写入 c }

// 后面其他函数会用 range 来遍历,所以一定要 close ,重要!
close(c)
}

对于函数 2 ,由于会用多个 goroutine 并发,那么每一次都需要一个 sync.Add(1) 来加入,所以每一次我们还要从 函数 2 里减去这个线程

原函数 2 伪代码:
func dealInfo(path string, typeDict map[string]int, c <-chan string){
for _, filename := range c {
判断文件;
处理文件;
}
}

现在改写为:
func dealInfo(path string, typeDict map[string]int, c <-chan string){
defer sync.Done()

for _, filename := range c {
判断文件;
处理文件;
}
}

非常简单,就是在循环前加一个 defer sync.Done() 就可以了。

最后,我们来写主函数的伪代码:

<====

import ("sync", ... )

var wg sync.WaitGroup // 为了创建多线程并发,准备线程池

func getInfo( ... ) // 实现 func1

func dealInfo( ... ) // 实现 func2

func main(){

c := make(chan string, 1000)

wg.Add(1)
go 函数 1

for i:=0; i<16; i++ {
wg.Add(1)
go 函数 2
}

wg.Wait()
}

====>

这里应该就能充分暴露前面改写过程中加入的奇怪东西的目的了 😄

可以发现,wg.Add(1) 之后,一定会紧跟一个带有 defer wg.Done() 的函数,来实现线程加减的匹配

而对于比较复杂的函数 2 ,我们通过一个循环来加入 N 个 goroutine 线程。wg.Add(1) 放在循环里面,同时每个 wg.Add() 都必然对应一个 defer wg.Done() 来匹配

最后,别忘了放一个 wg.Wait() 来通知主线程等待所有 wg 的线程执行完毕——它靠的就是不断 Add ,之后又不断 Done ,直到池子里线程归零的那一瞬来判断任务全部结束的。所以 Add 和 Done 必须匹配

另外一个之前没有提到的小改动是,我们建立 c (chan string) 的时候,还给了它一些缓存。这样,由于 func1 处理得很快,就可以预存一些结果到 c 里面,在面对 16 个 go func2 的时候,就能保证每个 func2 总是能拿到东西来处理,就不会空闲等待了。这个 N ,我在哪看到资料说是最大 10000 个,好像可以通过配置修改。不过对于大部分的场景,如果要修改这个参数,不如优化代码才是正道

还有一个地方是,我们在循环加入 函数 2 goroutine 的时候,wg.Add(1) 放在了循环里面。由于我知道这里的循环会创建 16 个 goroutine ,所以我们也可以一开始就在循环外面 wg.Add(16) 把它一口气全加进去。由于每个循环有一个 defer wg.Done() ,所以最后线程池还是可以归零的。只是这样写如果后期要扩充数量的话会有点不好维护,还是每个循环 +1 ,N 则通过配置文件来提供更妥当。
2022-11-06 17:40:27 +08:00
回复了 xt1990xt19900 创建的主题 Apple ventura 建议升级吗
@gilgameshhh 内录这么重要的功能……
2022-08-12 11:57:31 +08:00
回复了 terryl 创建的主题 iOS iPhone11 在升级了最新的 iOS16 Public Beta 以后,耗电令我担忧。
谢谢大佬们趟雷……
第一个 beta 因为发热回退了,还丢了健康记录
没想到到第五个 beta 了还这样
2022-07-07 16:20:19 +08:00
回复了 kxxoling 创建的主题 Apple 完全无法理解🍎这个快捷设置的意义
@starrystarry 我说怎么 UI 和图标变成这个鬼样子……
因为发热所以回 iOS15 了
2022-06-26 22:02:21 +08:00
回复了 janeedel 创建的主题 Apple beta2 终于来了
看样子生产主力机都不能上了。beta1 已经让我滚回 15 还掉了一堆东西
2022-06-26 21:54:50 +08:00
回复了 Lionad 创建的主题 Apple 我悟了,折腾什么桌面,最简洁的就是直接放一个 MacBook
我想到一个说法:差生文具多😂
就是个梗,不针对任何事情
2022-06-22 19:41:46 +08:00
回复了 MID 创建的主题 MacBook Pro m1 max 除了用来剪片,还能用来干什么?
全干工程师最近突然要用 blender 了,发现 pro 有点不够用……
2022-06-22 19:39:31 +08:00
回复了 makeitwork 创建的主题 MacBook Pro m1 max 用啥都快,就是辣鸡 office 还是那么卡顿
有没有可能是正版软件受害者
比如保存的时候会访问云端,尽管不保存到云端但还是要访问一下这样……
2022-06-17 10:03:45 +08:00
回复了 jayce789 创建的主题 Apple MAC 电脑两个触控板分别控制两个屏幕的一些思考
@yyfearth 妙啊, 单位的工作站有救了!
2022-06-16 20:59:53 +08:00
回复了 YoungKing6 创建的主题 Apple 618 MBP 外接键盘推荐
mac 键盘的精髓在于偏短的 space 以及两侧的 cmd
很多键盘说是兼容 Mac ,但是 cmd 的位置真是太难用了……
2022-06-16 11:38:09 +08:00
回复了 jayce789 创建的主题 Apple MAC 电脑两个触控板分别控制两个屏幕的一些思考
@yyfearth 愿闻其详,这个要咋操作。单位的工作站想利用一下
2022-06-15 11:07:25 +08:00
回复了 zhouwb 创建的主题 Apple Mac 上的 docker 怎么让容器 ip 与宿主同一网段
@q1angch0u 多谢大佬, 我也很苦恼 docker desktop 占用资源有点多的. 我也不跑啥大的东西
1 ... 18  19  20  21  22  23  24  25  26  27 ... 50  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2820 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 33ms · UTC 14:42 · PVG 22:42 · LAX 06:42 · JFK 09:42
Developed with CodeLauncher
♥ Do have faith in what you're doing.