<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>干徒的博客</title><link>https://ganto.cn</link><description>干徒 (Ganto) 的个人技术博客，分享 Rust、前端、WebAssembly 等编程技术文章。</description><language>zh-CN</language><atom:link href="https://ganto.cn/feed.xml" rel="self" type="application/rss+xml"/><item>
  <title>人工智能（AI）基础解析</title>
  <link>https://ganto.cn/post/20260129</link>
  <guid isPermaLink="true">https://ganto.cn/post/20260129</guid>
  <pubDate>2026-01-29 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>人工智能（AI）已经越来越融入我们的生活，从智能助手到智能机器人，从智能交通到智能医疗，AI正在改变我们的世界。</description>
  <category>Artificial Intelligence</category>
</item>
<item>
  <title>Dioxus基于Rust的多平台开发框架</title>
  <link>https://ganto.cn/post/20250609</link>
  <guid isPermaLink="true">https://ganto.cn/post/20250609</guid>
  <pubDate>2025-06-09 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
官网：https://dioxuslabs.com/

Dioxus 是用于构建全栈 Web、桌面和移动应用程序的 Rust 框架。使用实时热重载进行迭代，添加服务器函数，并在创纪录的时间内进行部署。
</description>
  <category>Rust</category>
  <category>Dioxus</category>
</item>
<item>
  <title>Rust 案例 - 计算器</title>
  <link>https://ganto.cn/post/20250410</link>
  <guid isPermaLink="true">https://ganto.cn/post/20250410</guid>
  <pubDate>2025-04-10 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# Rust 案例 - 计算器

```rust
use std::io;
use std::io::Write;

fn main() {
    let mut user_typer = UserTyper::new(CommandLineComputer);
    user_typer.type_expr();
    println!(&quot;Result: {}&quot;, user_typer.compute());
}

trait Computer {
    fn compute(&amp;self, expr: &amp;str) -&gt; i32;
}

struct CommandLineCompu</description>
  <category>Rust</category>
  <category>技术</category>
</item>
<item>
  <title>Rust镜像源</title>
  <link>https://ganto.cn/post/20250313</link>
  <guid isPermaLink="true">https://ganto.cn/post/20250313</guid>
  <pubDate>2025-03-13 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# Rust镜像源

## 配置Rust镜像源

配置文件位置  
`~/.cargo/config.toml`

修改 config.toml

```toml
[source.crates-io]
replace-with = &apos;aliyun&apos;
[source.aliyun]
registry = &quot;sparse+https://mirrors.aliyun.com/crates.io-index/&quot;

```
</description>
  <category>Rust</category>
  <category>技术</category>
</item>
<item>
  <title>Rust所有权</title>
  <link>https://ganto.cn/post/20250220-2</link>
  <guid isPermaLink="true">https://ganto.cn/post/20250220-2</guid>
  <pubDate>2025-02-20 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# Rust所有权

所有权系统是Rust中的一大特点  
今日靓仔我啊，就来体验一番

我们先来看一段代码

```rust
fn main() {
    let s1 = String::from(&quot;hello&quot;);
    let s2 = s1; // s1 的所有权转移给了 s2
    println!(&quot;s1: {}, s2: {}&quot;, s1, s2); // 报错，s1 已经被移动了
}

```

***你可能不了解rust代码，那么按照你熟悉的语言去理解他，大同小异***

代码中先定义了一个String字符串类型的变量 `s1`

然后紧接着定义了一个变量 `s2`，</description>
  <category>Rust</category>
  <category>后端</category>
  <category>技术</category>
</item>
<item>
  <title>JavaScript 高阶函数之 reduce</title>
  <link>https://ganto.cn/post/20250220</link>
  <guid isPermaLink="true">https://ganto.cn/post/20250220</guid>
  <pubDate>2025-02-20 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# JavaScript 高阶函数之 reduce

&gt; MDN：[https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global\_Objects/Array/reduce](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)

关于reduce函数，我们再熟悉不过了，我们通常用他对数据进行求和，也被称为**累加器**

reduce常见用例如下：

```js
let g</description>
  <category>JavaScript</category>
  <category>Vue</category>
  <category>前端</category>
  <category>技术</category>
</item>
<item>
  <title>JavaScript中的&quot;事件冒泡&quot;与&quot;事件捕获&quot;</title>
  <link>https://ganto.cn/post/20241220</link>
  <guid isPermaLink="true">https://ganto.cn/post/20241220</guid>
  <pubDate>2024-12-20 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# JavaScript中的&quot;事件冒泡&quot;与&quot;事件捕获&quot;

## 前言

Capture：事件捕获  
Bubble：事件冒泡

![](https://img2024.cnblogs.com/blog/2229842/202412/2229842-20241220165118171-411205481.png)  
如图所示，大致展示了事件冒泡和事件捕获的流程

可能还有点迷惑，无妨，继续往下看

## 事件冒泡展示

我们先创建一个嵌套的HTML结构

```html
&lt;div class=&quot;div1&quot;&gt;
    &lt;p&gt;div1&lt;/p&gt;
    &lt;div class=&quot;div2&quot;&gt;
   </description>
  <category>JavaScript</category>
  <category>技术</category>
</item>
<item>
  <title>今天，学习Web Component</title>
  <link>https://ganto.cn/post/20240511</link>
  <guid isPermaLink="true">https://ganto.cn/post/20240511</guid>
  <pubDate>2024-05-11 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# 今天，学习Web Component

[Web Component MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components)  
[阮一峰 web components](https://www.ruanyifeng.com/blog/2019/08/web_components.html)

## 例子1：

```html
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; c</description>
  <category>JavaScript</category>
  <category>技术</category>
</item>
<item>
  <title>Gin中间件上下文中的Set、Get函数的用法</title>
  <link>https://ganto.cn/post/20240415</link>
  <guid isPermaLink="true">https://ganto.cn/post/20240415</guid>
  <pubDate>2024-04-15 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# Gin中间件上下文中的Set、Get函数的用法

## Code

如下代码所示，中间件`middlewareA`内部通过`c.Set(&quot;middlewareA_key&quot;, str)`将参数设置到上下文中  
所以中间件`middlewareB`可以通过`c.Get(&quot;middlewareA_key&quot;)`获取到上下文中传递的值，并将值进行了修改，然后继续通过上下文进行了传递  
然后在控制器函数中可以通过上下文`c.Keys[&quot;middlewareB_key&quot;]`的方式获取

```go
package main

import (
	&quot;fmt&quot;
	&quot;github.com/gin-gon</description>
  <category>Golang</category>
  <category>后端</category>
  <category>技术</category>
</item>
<item>
  <title>React中forwardRef的用法</title>
  <link>https://ganto.cn/post/20240412</link>
  <guid isPermaLink="true">https://ganto.cn/post/20240412</guid>
  <pubDate>2024-04-12 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# React中forwardRef的用法

&gt; 官网文档：[https://zh-hans.react.dev/reference/react/forwardRef](https://zh-hans.react.dev/reference/react/forwardRef)

今天我们就一起学习一下React中的ref怎么获取组件实例，只讨论函数式组件中的ref

如下代码，我们直接在App根组件中，意图只使用ref就获取Footer组件实例

细心的同学可能已经发现控制台报错了，提示我们应该使用forwardRef，并且编辑器也提示`ref={footRef}`类型不对

这是因为Rea</description>
  <category>JavaScript</category>
  <category>React</category>
  <category>TypeScript</category>
  <category>前端</category>
  <category>技术</category>
</item>
<item>
  <title>5分钟快速入门Taro</title>
  <link>https://ganto.cn/post/20240402</link>
  <guid isPermaLink="true">https://ganto.cn/post/20240402</guid>
  <pubDate>2024-04-02 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# 5分钟快速入门Taro

## Taro介绍

Taro是由凹凸实验室开发的一个开放式跨端跨框架，支持使用 React/Vue/Nerv 等框架来开发 [微信](https://mp.weixin.qq.com/) / [京东](https://mp.jd.com/?entrance=taro) / [百度](https://smartprogram.baidu.com/) / [支付宝](https://mini.open.alipay.com/) / [字节跳动](https://developer.open-douyin.com/) / [QQ](https://q.qq.com/</description>
  <category>JavaScript</category>
  <category>React</category>
  <category>TypeScript</category>
  <category>Vue</category>
  <category>前端</category>
  <category>技术</category>
</item>
<item>
  <title>React中使用Immer编写简洁的更新逻辑</title>
  <link>https://ganto.cn/post/20240328</link>
  <guid isPermaLink="true">https://ganto.cn/post/20240328</guid>
  <pubDate>2024-03-28 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# React中使用Immer编写简洁的更新逻辑

在 [浅谈React中的mutation](https://www.cnblogs.com/ganto/articles/18098638) 一文中，突出表达了对象和数组类型的state，不宜直接修改原对象和数组，直接修改会制造一个mutation，并且无法触发React的重新渲染

在官方文档中提到一个库 [Immer](https://github.com/immerjs/use-immer) ，Immer 可以让我们直接修改对象和数组。

## useImmer

需要先安装use-immer库

```sh
pnpm add use</description>
  <category>JavaScript</category>
  <category>React</category>
  <category>前端</category>
  <category>技术</category>
</item>
<item>
  <title>浅谈React中的mutation</title>
  <link>https://ganto.cn/post/20240327</link>
  <guid isPermaLink="true">https://ganto.cn/post/20240327</guid>
  <pubDate>2024-03-27 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# 浅谈React中的mutation

&gt; 官方文档：[保持组件纯粹](https://zh-hans.react.dev/learn/keeping-components-pure)、[更新 state 中的对象](https://zh-hans.react.dev/learn/updating-objects-in-state)、[更新 state 中的数组](https://zh-hans.react.dev/learn/updating-arrays-in-state)

# 保持组件纯粹

这里说的纯粹也就是JS中的纯函数

那么，什么是纯函数？

纯函数 通常具有如下特征（摘自</description>
  <category>JavaScript</category>
  <category>React</category>
  <category>技术</category>
</item>
<item>
  <title>Go语言高并发编程初探</title>
  <link>https://ganto.cn/post/20240326</link>
  <guid isPermaLink="true">https://ganto.cn/post/20240326</guid>
  <pubDate>2024-03-26 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# Go语言高并发编程初探

在当今这个数据爆炸的时代，高并发编程已成为开发者们必须掌握的技能之一。Go语言，由于其出色的并发支持和简洁的语法，正逐渐成为高并发编程领域的热门选择。本文将带您走进Go语言高并发编程的世界，探索其中的奥秘。

**一、Go语言的并发模型**

Go语言采用了CSP（Communicating Sequential Processes）并发模型，即通过通道（channel）在协程（goroutine）之间进行通信。协程是Go语言实现并发的基本单位，它们比线程更轻量级，可以创建成千上万个而不会给系统带来太大负担。通道则用于协程之间的数据传递，使得并发编程更加安全、高</description>
  <category>AI</category>
  <category>Golang</category>
  <category>后端</category>
  <category>高并发</category>
  <category>技术</category>
</item>
<item>
  <title>windows终端命令受限</title>
  <link>https://ganto.cn/post/20240315</link>
  <guid isPermaLink="true">https://ganto.cn/post/20240315</guid>
  <pubDate>2024-03-15 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# windows终端命令受限

在windows系统上，通过以下命令安装pnpm包管理工具，然后在终端执行`pnpm -v`会报错

```sh
npm install -g pnpm

pnpm -v # 报错

```

运行get-ExecutionPolicy，显示Restricted（受限的）

```sh
get-ExecutionPolicy
Restricted

```

运行set-ExecutionPolicy RemoteSigned，设置RemoteSigned

```sh
set-ExecutionPolicy RemoteSigned

```

再次查看
</description>
  <category>Windows</category>
  <category>技术</category>
</item>
<item>
  <title>TypeScript类型取反</title>
  <link>https://ganto.cn/post/20240313</link>
  <guid isPermaLink="true">https://ganto.cn/post/20240313</guid>
  <pubDate>2024-03-13 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# TypeScript类型取反

读码见意

```ts
function func(arg: number) {}
func(1)
func(&quot;zs&quot;) // ERROR Argument of type &apos;string&apos; is not assignable to parameter of type &apos;number&apos;.

```

如想要将函数参数定义为非number的其他类型，则可以这样

```ts
function func&lt;T&gt;(arg: T extends number ? never : T) {}
func(1) // ERROR Argument of type &apos;num</description>
  <category>TypeScript</category>
  <category>技术</category>
</item>
<item>
  <title>实现一个丝滑的暗黑模式切换动画</title>
  <link>https://ganto.cn/post/20240102</link>
  <guid isPermaLink="true">https://ganto.cn/post/20240102</guid>
  <pubDate>2024-01-02 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# 实现一个丝滑的暗黑模式切换动画

&gt; 体验：[https://ganto.me](https://ganto.me)

&gt; 参考内容：  
&gt; 参考文章：[https://juejin.cn/post/7269388083342082107](https://juejin.cn/post/7269388083342082107)  
&gt; MDN：[https://developer.mozilla.org/zh-CN/docs/Web/API/View\_Transitions\_API](https://developer.mozilla.org/zh-CN/docs/Web/API/</description>
  <category>Vue</category>
  <category>前端</category>
  <category>技术</category>
</item>
<item>
  <title>Vue3.3+ 新特性 defineOptions</title>
  <link>https://ganto.cn/post/20231221</link>
  <guid isPermaLink="true">https://ganto.cn/post/20231221</guid>
  <pubDate>2023-12-21 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# Vue3.3+ 新特性 defineOptions

`defineOptions`是一个宏，是在Vue3.3+中新增的新特性

# defineOptions配置项

## name

在Vue3.3之前，组件的默认组件名为.vue单文件组件\[SFC\]文件的名字，如果需要修改组件名则需要结合Options API进行配置

```vue
&lt;!-- src/components/Com.vue --&gt;
&lt;script setup&gt;

&lt;/script&gt;

&lt;script&gt;
export default {
  name: &apos;ComponentName&apos;
}
&lt;/script&gt;

&lt;t</description>
  <category>JavaScript</category>
  <category>Vue</category>
  <category>前端</category>
  <category>技术</category>
</item>
<item>
  <title>Vue3 实验性特性 defineModel</title>
  <link>https://ganto.cn/post/20231221-2</link>
  <guid isPermaLink="true">https://ganto.cn/post/20231221-2</guid>
  <pubDate>2023-12-21 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# Vue3 实验性特性 defineModel

&gt; 在Vue3.4中，defineModel宏已经被正式启用，无需配置，直接可用

# 启用defineModel

目前\[Vue3.3.13\]defineModel宏是实验性特性，如果需要使用该宏，需要在`vite.config.js`配置以下内容

```js
export default defineConfig({
  plugins: [
    vue({
      script: {
        defineModel: true
      }
    }),
  ],
})

```

因为是实验性功能，在运行项</description>
  <category>JavaScript</category>
  <category>Vue</category>
  <category>前端</category>
  <category>技术</category>
</item>
<item>
  <title>JavaScript闭包直接修改内部属性</title>
  <link>https://ganto.cn/post/20231117</link>
  <guid isPermaLink="true">https://ganto.cn/post/20231117</guid>
  <pubDate>2023-11-17 00:00:00 +0800</pubDate>
  <author>干徒</author>
  <description>
# JavaScript闭包直接修改内部属性

## 事例代码

```js
var o = (function() {
    var obj = {
        a: 1,
        b: 2,
    }
    return {
        get: function(k) {
            return obj[k]
        }
    }
})()

```

## 说明

如上一段代码，在不改变原代码的情况下，修改obj对象中的a、b属性。

## 分析

代码使用了闭包，返回一个对象，对象中有一个get函数，这个get函数只能通过`o.get(</description>
  <category>JavaScript</category>
  <category>技术</category>
</item>
</channel>
</rss>
