Appearance
常见模式对比
本指南展示 TypeScript 和 Targo 中常见编程模式的对比,帮助你快速适应 Targo 的编程风格。
异步操作
单个异步操作
typescript
// TypeScript
async function fetchUser(id: number): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
const user = await fetchUser(123);
// Targo
import { Get } from "net/http";
import { Unmarshal } from "encoding/json";
import { ReadAll } from "io";
function fetchUser(id: int): chan<User> {
let ch = chan.make<User>();
go(() => {
let [resp, err] = Get(`/api/users/${id}`);
if (err != null) {
ch.close();
return;
}
let [body, err2] = ReadAll(resp.Body);
resp.Body.Close();
if (err2 != null) {
ch.close();
return;
}
let user = zero<User>();
Unmarshal(body, ref(user));
ch.send(user);
ch.close();
});
return ch;
}
let userCh = fetchUser(123);
let user = userCh.receive();并行请求
typescript
// TypeScript - Promise.all
const [user, posts, comments] = await Promise.all([
fetchUser(id),
fetchPosts(id),
fetchComments(id)
]);
// Targo - 并发 goroutine
let userCh = chan.make<User>();
let postsCh = chan.make<slice<Post>>();
let commentsCh = chan.make<slice<Comment>>();
go(() => { userCh.send(fetchUser(id)); });
go(() => { postsCh.send(fetchPosts(id)); });
go(() => { commentsCh.send(fetchComments(id)); });
let user = userCh.receive();
let posts = postsCh.receive();
let comments = commentsCh.receive();超时处理
typescript
// TypeScript
const timeout = (ms: number) =>
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), ms)
);
try {
const result = await Promise.race([
fetchData(),
timeout(5000)
]);
} catch (error) {
console.error('Request timed out');
}
// Targo
import { After } from "time";
let dataCh = fetchData();
let timeout = After(5 * time.Second);
switch (chan.$select) {
case dataCh.$recv:
let result = dataCh.$value;
console.log("Got data:", result);
break;
case timeout.$recv:
console.error("Request timed out");
break;
}数组操作
Map(转换)
typescript
// TypeScript
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2);
// Targo - 使用 Array
let numbers: Array<int> = [1, 2, 3, 4, 5];
let doubled = numbers.map(x => x * 2);
// Targo - 使用 slice(手动循环)
let numbers2: slice<int> = [1, 2, 3, 4, 5];
let doubled2 = slice.make<int>(numbers2.len());
for (let i = 0; i < numbers2.len(); i++) {
doubled2[i] = numbers2[i] * 2;
}Filter(过滤)
typescript
// TypeScript
const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(x => x % 2 === 0);
// Targo - 使用 Array
let numbers: Array<int> = [1, 2, 3, 4, 5];
let evens = numbers.filter(x => x % 2 == 0);
// Targo - 使用 slice(手动循环)
let numbers2: slice<int> = [1, 2, 3, 4, 5];
let evens2 = slice.make<int>(0, numbers2.len());
for (const num of numbers2) {
if (num % 2 == 0) {
evens2 = slice.append(evens2, num);
}
}Reduce(归约)
typescript
// TypeScript
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, x) => acc + x, 0);
// Targo - 使用 Array
let numbers: Array<int> = [1, 2, 3, 4, 5];
let sum = numbers.reduce((acc, x) => acc + x, 0);
// Targo - 使用 slice(手动循环)
let numbers2: slice<int> = [1, 2, 3, 4, 5];
let sum2: int = 0;
for (const num of numbers2) {
sum2 += num;
}Find(查找)
typescript
// TypeScript
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
const user = users.find(u => u.id === 2);
// Targo - 使用 Array
let users: Array<User> = [
{ id: 1, name: "Alice" } as User,
{ id: 2, name: "Bob" } as User
];
let user = users.find(u => u.id == 2);
// Targo - 使用 slice(手动循环)
let users2: slice<User> = [
{ id: 1, name: "Alice" } as User,
{ id: 2, name: "Bob" } as User
];
let user2: User | null = null;
for (const u of users2) {
if (u.id == 2) {
user2 = u;
break;
}
}对象操作
对象字面量
typescript
// TypeScript
const user = {
id: 1,
name: 'Alice',
email: 'alice@example.com'
};
// Targo
class User {
id: int;
name: string;
email: string;
}
let user = {
id: 1,
name: "Alice",
email: "alice@example.com"
} as User;对象解构
typescript
// TypeScript
const { name, email } = user;
// Targo
let name = user.name;
let email = user.email;对象合并
typescript
// TypeScript
const defaults = { host: 'localhost', port: 3000 };
const config = { ...defaults, port: 8080 };
// Targo
class Config {
host: string;
port: int;
}
let defaults = { host: "localhost", port: 3000 } as Config;
let config = { host: defaults.host, port: 8080 } as Config;遍历对象属性
typescript
// TypeScript
const obj = { a: 1, b: 2, c: 3 };
for (const [key, value] of Object.entries(obj)) {
console.log(key, value);
}
// Targo - 使用 map
let m = map.of<string, int>(
["a", 1],
["b", 2],
["c", 3]
);
for (const [key, value] of m) {
console.log(key, value);
}类继承 vs 组合
简单继承
typescript
// TypeScript
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
speak(): void {
console.log(`${this.name} makes a sound`);
}
}
class Dog extends Animal {
bark(): void {
console.log('Woof!');
}
}
const dog = new Dog('Buddy');
dog.speak(); // "Buddy makes a sound"
dog.bark(); // "Woof!"
// Targo - 使用组合
class Animal {
name: string;
speak(): void {
console.log(`${this.name} makes a sound`);
}
}
class Dog extends Embedding({ animal: {} as Animal }) {
bark(): void {
console.log("Woof!");
}
}
function NewDog(name: string): Dog {
let dog = new Dog();
dog.animal.name = name;
return dog;
}
let dog = NewDog("Buddy");
dog.animal.speak(); // "Buddy makes a sound"
dog.bark(); // "Woof!"多重继承
typescript
// TypeScript - 使用 mixin
class Flyable {
fly(): void {
console.log('Flying');
}
}
class Swimmable {
swim(): void {
console.log('Swimming');
}
}
class Duck extends Flyable {
// 只能继承一个类
}
// Targo - 使用多重组合
class Flyable {
fly(): void {
console.log("Flying");
}
}
class Swimmable {
swim(): void {
console.log("Swimming");
}
}
class Duck extends Embedding({
flyable: {} as Flyable,
swimmable: {} as Swimmable
}) {
quack(): void {
console.log("Quack!");
}
}
let duck = new Duck();
duck.flyable.fly(); // "Flying"
duck.swimmable.swim(); // "Swimming"
duck.quack(); // "Quack!"错误处理
基本错误处理
typescript
// TypeScript
function divide(a: number, b: number): number {
if (b === 0) {
throw new Error('Division by zero');
}
return a / b;
}
try {
const result = divide(10, 0);
} catch (error) {
console.error('Error:', error.message);
}
// Targo
import { New } from "errors";
function divide(a: float64, b: float64): [float64, error | null] {
if (b == 0) {
return [0, New("division by zero")];
}
return [a / b, null];
}
let [result, err] = divide(10, 0);
if (err != null) {
console.error("Error:", err);
}错误传播
typescript
// TypeScript
async function processFile(path: string): Promise<string> {
try {
const data = await readFile(path);
const parsed = await parseData(data);
return parsed;
} catch (error) {
throw new Error(`Failed to process file: ${error.message}`);
}
}
// Targo
import { Errorf } from "fmt";
function processFile(path: string): [string, error | null] {
let [data, err] = readFile(path);
if (err != null) {
return ["", Errorf("failed to read file: %w", err)];
}
let [parsed, err2] = parseData(data);
if (err2 != null) {
return ["", Errorf("failed to parse data: %w", err2)];
}
return [parsed, null];
}自定义错误
typescript
// TypeScript
class ValidationError extends Error {
constructor(message: string) {
super(message);
this.name = 'ValidationError';
}
}
throw new ValidationError('Invalid input');
// Targo
class ValidationError {
message: string;
Error(): string {
return this.message;
}
}
function NewValidationError(message: string): error {
return { message } as ValidationError;
}
// 使用
return [zero<Result>(), NewValidationError("invalid input")];模块系统
导出和导入
typescript
// TypeScript
// math.ts
export function add(a: number, b: number): number {
return a + b;
}
export const PI = 3.14159;
// main.ts
import { add, PI } from './math';
// Targo
// math.ts
export function add(a: int, b: int): int {
return a + b;
}
export const PI: float64 = 3.14159;
// main.ts
import { add, PI } from "./math";默认导出
typescript
// TypeScript
// user.ts
export default class User {
name: string;
}
// main.ts
import User from './user';
// Targo - 没有默认导出,使用命名导出
// user.ts
export class User {
name: string;
}
// main.ts
import { User } from "./user";导入 Go 包
typescript
// Targo
import { Println, Printf, Sprintf } from "fmt";
import { ReadFile, WriteFile } from "os";
import { Get, Post } from "net/http";
import { Sleep } from "time";
// 使用别名
import { Println as print } from "fmt";
print("Hello");工具函数
Debounce
typescript
// TypeScript
function debounce<T extends (...args: any[]) => any>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
}
// Targo
import { AfterFunc, Stop } from "time";
function debounce(fn: () => void, wait: time.Duration): () => void {
let timer: Timer | null = null;
return () => {
if (timer != null) {
Stop(timer);
}
timer = AfterFunc(wait, fn);
};
}Throttle
typescript
// TypeScript
function throttle<T extends (...args: any[]) => any>(
func: T,
limit: number
): (...args: Parameters<T>) => void {
let inThrottle: boolean;
return (...args) => {
if (!inThrottle) {
func(...args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// Targo
import { NewTicker } from "time";
function throttle(fn: () => void, interval: time.Duration): chan<bool> {
let ticker = NewTicker(interval);
let stopCh = chan.make<bool>();
go(() => {
for {
switch (chan.$select) {
case ticker.C.$recv:
fn();
break;
case stopCh.$recv:
ticker.Stop();
return;
}
}
});
return stopCh;
}Retry
typescript
// TypeScript
async function retry<T>(
fn: () => Promise<T>,
maxAttempts: number
): Promise<T> {
for (let i = 0; i < maxAttempts; i++) {
try {
return await fn();
} catch (error) {
if (i === maxAttempts - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
throw new Error('Max attempts reached');
}
// Targo
import { Sleep } from "time";
function retry<T>(
fn: () => [T, error | null],
maxAttempts: int
): [T, error | null] {
for (let i = 0; i < maxAttempts; i++) {
let [result, err] = fn();
if (err == null) {
return [result, null];
}
if (i < maxAttempts - 1) {
Sleep(time.Second * (i + 1));
}
}
return [zero<T>(), New("max attempts reached")];
}数据结构
Stack(栈)
typescript
// TypeScript
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
peek(): T | undefined {
return this.items[this.items.length - 1];
}
isEmpty(): boolean {
return this.items.length === 0;
}
}
// Targo
class Stack<T> {
#items: slice<T>;
push(item: T): void {
this.#items = slice.append(this.#items, item);
}
pop(): T | null {
if (this.#items.len() == 0) {
return null;
}
let item = this.#items[this.#items.len() - 1];
this.#items = this.#items.slice(0, this.#items.len() - 1);
return item;
}
peek(): T | null {
if (this.#items.len() == 0) {
return null;
}
return this.#items[this.#items.len() - 1];
}
isEmpty(): bool {
return this.#items.len() == 0;
}
}Queue(队列)
typescript
// TypeScript
class Queue<T> {
private items: T[] = [];
enqueue(item: T): void {
this.items.push(item);
}
dequeue(): T | undefined {
return this.items.shift();
}
isEmpty(): boolean {
return this.items.length === 0;
}
}
// Targo
class Queue<T> {
#items: slice<T>;
enqueue(item: T): void {
this.#items = slice.append(this.#items, item);
}
dequeue(): T | null {
if (this.#items.len() == 0) {
return null;
}
let item = this.#items[0];
this.#items = this.#items.slice(1);
return item;
}
isEmpty(): bool {
return this.#items.len() == 0;
}
}性能优化
预分配容量
typescript
// TypeScript
const items: number[] = [];
for (let i = 0; i < 1000; i++) {
items.push(i);
}
// Targo - 预分配容量
let items = slice.make<int>(0, 1000); // 容量 1000
for (let i = 0; i < 1000; i++) {
items = slice.append(items, i); // 不会触发重新分配
}避免不必要的分配
typescript
// TypeScript
function processItems(items: number[]): number[] {
return items.map(x => x * 2); // 创建新数组
}
// Targo - 原地修改
function processItems(items: slice<int>): void {
for (let i = 0; i < items.len(); i++) {
items[i] *= 2; // 原地修改,不分配新内存
}
}使用 sync.Pool 复用对象
typescript
// Targo
import { Pool } from "sync";
let bufferPool = new Pool();
bufferPool.New = () => slice.make<byte>(0, 1024);
function processData(data: slice<byte>): void {
// 从池中获取 buffer
let buf = bufferPool.Get() as slice<byte>;
// 使用 buffer
// ...
// 清空并归还到池中
buf.clear();
bufferPool.Put(buf);
}下一步
参考资源
- Effective Go - Go 最佳实践
- Go by Example - Go 代码示例
- TypeScript 到 Targo - 语言特性对比