惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
Webroot Blog
Webroot Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Threat Research - Cisco Blogs
V2EX - 技术
V2EX - 技术
L
LINUX DO - 热门话题
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
S
Schneier on Security
I
InfoQ
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The GitHub Blog
The GitHub Blog
S
Security @ Cisco Blogs
O
OpenAI News
W
WeLiveSecurity
Vercel News
Vercel News
阮一峰的网络日志
阮一峰的网络日志
Simon Willison's Weblog
Simon Willison's Weblog
人人都是产品经理
人人都是产品经理
Cloudbric
Cloudbric
The Last Watchdog
The Last Watchdog
The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
GbyAI
GbyAI
NISL@THU
NISL@THU
T
Tailwind CSS Blog
V
Visual Studio Blog
PCI Perspectives
PCI Perspectives
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
D
DataBreaches.Net
B
Blog RSS Feed
N
News and Events Feed by Topic
N
News and Events Feed by Topic
H
Heimdal Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
腾讯CDC
Latest news
Latest news
V
Vulnerabilities – Threatpost
Hacker News: Ask HN
Hacker News: Ask HN
WordPress大学
WordPress大学
V
V2EX
aimingoo的专栏
aimingoo的专栏
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Register - Security
The Register - Security
Help Net Security
Help Net Security

smallyu的博客

为什么买的加密货币一定要去中心化 RISC-V 虚拟机无法代替 EVM 虚拟机 Polkadot 的 Existential Deposit 机制错在哪里 利息,套利,交易策略,金融市场 LayerZero 从来不挑战比特币的地位 默认参数引起的以太坊节点运行错误 硬件钱包与资产安全 预测市场比币圈更赌场 为什么去中心化的跨链桥不可能实现 我对于 AI 时代的答案 不要投资任何隐私币 区块链技术世界的三大真理 以太坊 AA 钱包的致命问题是什么 基于 AI 语义执行的 MCP 区块链的设计 一个集成 Geth 和 CometBFT 的兼容层 我的加密货币定投策略(二) DeFi 基础: 理解 AMM 定价机制 Go 语言 GMP 调度器的原理是什么 Web3 项目分析计划 对 Psyche Network 项目的分析 continuation 教程: 理解 CPS 如何开发一个比特币符文(Runes)协议 比特币脚本开发教程 我从王垠的计算机科学视频班学到了什么 区块链技术面试题(2025年版) Rust 语言容易让新手困惑的一个“过度优化” Solana 智能合约开发教程 (1) 尝试开发一个最小 EVM 虚拟机 基于 ZK 的链上身份系统设计 一个 Web3 打赏系统的设计 鼓吹 Cursor 的人技术能力都差 关于 Code Review 的礼节 假如启动一个新的以太坊 PoS 网络 发行加密货币的最好方式 所有 BFT 共识的区块链都是中心化的 对 2025 年区块链行业的预测 Restaking 项目的经济难题 如何看懂任意区块链项目的技术架构 为什么不要做以太坊的二次开发 为什么不要做智能合约开发和 DeFi 开发 我的加密货币定投策略(一) PoS 类型的区块链如何处理分叉 Ethereum Casper 为什么需要 EIP-7251 区块链中的 PBFT 不需要第二次投票 开发者的思维方式 发币的核心要点 炒币投资的小 tips 为什么说 PoW 比 PoS 更加去中心化 牛市对普通人来说意味着什么 如何健康地远程工作 为什么比特币不用概率加密函数 程序员的 “服从权威” 心理 区块链技术面试题 如何区分公有链和联盟链 对 Layer 2 项目创业想法的回复 对区块链共识机制的理解 Pebbling Game 鹅卵石游戏 PDP 文件证明的局限性 不要小瞧 ChatGPT 为什么炒币不是一个好主意 一种在区块链上生成随机数的机制 为什么以太坊的私钥计算不可逆 关于以太坊的私钥碰撞 “猜均值的2/3” dApp 游戏设计 Proof of Storage/Space/Replication 的区别 Proofs of Retrievability 文件证明的含义 对 S-PDP 文件证明的示例和解释 我的加密货币交易机器人 对区块链行业的见闻 随机确认块的共识机制 VRF + BFT 共识引起交易失败的问题 为什么要重视编程思想 对 Web 3.0 的理解 GitBook 好用吗? 一种区块链节点存储扩容的方式 一种基于“自我中心主义”的共识机制 链表常见算法题及解析 基于 Multi-Linked List 的区块链设想 理解哈希函数与序列化 联盟链比公有链差在哪儿 在 Dijkstra 算法中保存路径 为什么数字货币使用区块链是政治问题 区块链:下一代数字身份认证体系的基石 网页技术能实现 3D 建模吗? 给区块链一个定义 从 Erlang 开始了解 Actor 模型 一种侧边导航栏的交互方式 Rust 的 ownership 是什么? Haskell 中的 Monad 是什么? 浅析 Libra 背后的区块链技术 对区块链的理性认识 Rust 基础语法概述 基于 Java 的爬虫框架 WebCollector Kotlin:简化版的 Scala JavaScript 有关联数组吗? Go 语言基本语法 Scala 语法基础 用 Scala 改写 Java 浅度实践 Python 获取海贼王更新信息 HTML5 音乐可视化
主流编程语言的异常处理机制
2019-04-24 · via smallyu的博客

主流编程语言的异常处理机制

2019-04-24

学习编程语言应该从语言特性入手,而不是编程语言本身。这里尝试对各种编程语言的异常和错误处理机制做一个横向的、简单的了解。涉及到的编程语言包括C、C++、Go、Java、Scala、Kotlin、Ruby、Rust、JavaScript、PHP、Python、Lisp。

C

C语言没有异常捕获机制。程序在发生错误时会设置一个错误代码errno,该变量是全局变量。C语言提供了perror()和strerror()函数来显示与errno相关的描述信息。perror()函数可以直接调用,入参是一个字符串,输出入参: 错误文本。strerror()函数入参是一个数字(错误码),返回一个指针,指针指向错误码对应的文本。

#include <stdio.h>
#include <errno.h>
#include <string.h>

void main ()
{
  // 打开一个不存在的文件,会发生错误
  fopen ("unexist.txt", "rb");

  // 2
  printf("%d\n", errno);

  // No such file or directory
  perror("");

  // No such file or directory
  printf("%s\n", strerror(errno));
}

C++

C++支持异常捕获机制。C++可以抛出或捕获两种内容,一种是int或char*之类的内容,程序可以捕获并抛出,这一点和Java相比有差异,因为Java并不支持直接抛出基本类型的异常:

#include <iostream>
#include <exception>
using namespace std;
int main () {
    try
    {
        throw "error";
    }
    catch(const char* msg)
    {
        cout << msg << endl;
    }
} 

// error

另一种内容就是类,可以是内置的标准异常类,或是自定义的异常类:

#include <iostream>
#include <exception>
using namespace std;
int main () {
    try
    {
        throw exception();
    }
    catch(std::exception& e)
    {
        cout << e.what() << endl;
    }
} 

// std::exception

Go

Go语言作为非OOP派系的编程语言,并不支持try-catch的语法,但仍然具有类似抛出和捕获的特性。Go语言有3个错误相关的关键字,panic()、recover()和defer。可以理解为,panic()函数抛出异常,recover()函数捕获异常,defer关键字定义最后也就是finally执行的内容:

package main
import "fmt"

func main() {
  defer func() {
    err := recover()
    fmt.Println(err)
  }()
  panic("error")
}

// error

Java

Java是纯粹的OOP语言,仅支持对象的抛出和捕获:

public class ErrorTest {
    public static void main(String[] args) {
        try {
            throw new Exception();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

// java.lang.Exception

Scala

Scala和Java是一个流派,同样仅支持对象的抛出和捕获,除了语法上和Java稍有差异,概念上基本是一jian样rong的:

object ErrorTest {
  def main(args: Array[String]): Unit = {
    try {
      throw new Exception()
    } catch {
      case e: Exception => print(e)
    }
  }
}

// java.lang.Exception

另外,Scala抛出的是Java的异常,也许Scala不能算作是独立的编程语言,而是依附于Java、为Java提供语法糖的编程语言。这一点值得深入思考和探究。

Kotlin

Kotlin和Scala是一种性质的语言,默认抛出的同样是Java的异常:

fun main(args: Array<String>) {
  try {
    throw Exception()
  } catch (e: Exception) {
    print(e)
  }
}

// java.lang.Exception

Ruby

Ruby使用关键字raise和rescue代替try和catch来实现异常的抛出和捕获。Ruby同样支持try-catch关键字,这里暂不讨论,因为我没搞清楚它的用法。

begin
  raise "error" 
  rescue Exception => e
    puts e
end

// error

Rust

Rust没有try-catch的语法,也没有类似Go的错误处理函数,而是用对错误处理进行过包装的Option<T>或Option的加强版Result<T, E>进行错误处理。Rust的模式匹配和Scala类似:

fn main() {
  match find() {
    None => println!("none"),
    Some(i) => println!("{}", i),
  }
}

fn find() -> Option<usize> {
  if 1 == 1 {
    return Some(1);
  }
  None
}

// 1

JavaScript

脚本语言在变量类型上不做强制约束,捕获时也就不能按照异常类型来做区分。抛出错误的内容还是相对自由的:

try {
  throw 1
} catch (e) {
  console.log(e)
}

// 1

try {
  throw new Error('')
} catch (e) {
  console.log(e)
}

// Error

PHP

PHP的try-catch和Java类似,并没有特殊之处:

<?php
  try {
      throw new Exception("error");
  } catch (Exception $e) {
      echo $e->getMessage();
  }

Python

Python在语法上能找到Ruby的影子,raise触发异常,execpt捕获异常:

try:
  raise
except:
  print("error")

Lisp

Lisp整体较复杂,Lisp捕获处理异常的内容暂时留坑。以下是Common Lisp触发错误的情形之一,declare会声明函数入参类型,传入错误参数将引发错误:

(defun df (a b)
  (declare (double-float a b))
  (* a b))
  
(df "1" 3)

// *** - *: "1" is not a number

后续

原先想梳理这些语言的大部分异常和错误处理相关概念,然而真正开始后发现比较困难,并且之前我没能区分”exception”和”checked exception”,以致从立意到标题到内容可能都有偏差。这次就先提及”exception”,之后讨论关于”checked exception”的内容。